diakonos 0.8.7 → 0.8.8
Sign up to get free protection for your applications and to get access to all the features.
- metadata +38 -59
- data/CHANGELOG +0 -238
- data/LICENCE +0 -21
- data/README +0 -75
- data/bin/diakonos +0 -6
- data/diakonos-256-colour.conf +0 -102
- data/diakonos.conf +0 -1233
- data/lib/diakonos.rb +0 -618
- data/lib/diakonos/array.rb +0 -15
- data/lib/diakonos/bignum.rb +0 -9
- data/lib/diakonos/bookmark.rb +0 -50
- data/lib/diakonos/buffer-hash.rb +0 -60
- data/lib/diakonos/buffer-management.rb +0 -73
- data/lib/diakonos/buffer.rb +0 -2044
- data/lib/diakonos/clipboard.rb +0 -47
- data/lib/diakonos/config.rb +0 -304
- data/lib/diakonos/ctag.rb +0 -28
- data/lib/diakonos/display.rb +0 -288
- data/lib/diakonos/enumerable.rb +0 -15
- data/lib/diakonos/finding.rb +0 -32
- data/lib/diakonos/fixnum.rb +0 -17
- data/lib/diakonos/functions.rb +0 -1420
- data/lib/diakonos/grep.rb +0 -78
- data/lib/diakonos/hash.rb +0 -108
- data/lib/diakonos/help.rb +0 -92
- data/lib/diakonos/hooks.rb +0 -13
- data/lib/diakonos/interaction.rb +0 -139
- data/lib/diakonos/keycode.rb +0 -110
- data/lib/diakonos/keying.rb +0 -124
- data/lib/diakonos/list.rb +0 -55
- data/lib/diakonos/logging.rb +0 -24
- data/lib/diakonos/object.rb +0 -6
- data/lib/diakonos/readline.rb +0 -274
- data/lib/diakonos/regexp.rb +0 -6
- data/lib/diakonos/sessions.rb +0 -70
- data/lib/diakonos/sized-array.rb +0 -48
- data/lib/diakonos/string.rb +0 -326
- data/lib/diakonos/text-mark.rb +0 -19
- data/lib/diakonos/vendor/fuzzy_file_finder.rb +0 -353
- data/lib/diakonos/window.rb +0 -32
- data/test/buffer-test.rb +0 -53
- data/test/clipboard-test.rb +0 -70
- data/test/diakonos-test.rb +0 -14
- data/test/hash-test.rb +0 -404
- data/test/regexp-test.rb +0 -26
- data/test/sizedarray-test.rb +0 -113
- data/test/string-test.rb +0 -160
data/lib/diakonos/array.rb
DELETED
data/lib/diakonos/bignum.rb
DELETED
data/lib/diakonos/bookmark.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Diakonos
|
2
|
-
|
3
|
-
class Bookmark
|
4
|
-
attr_reader :buffer, :row, :col, :name
|
5
|
-
|
6
|
-
def initialize( buffer, row, col, name = nil )
|
7
|
-
@buffer = buffer
|
8
|
-
@row = row
|
9
|
-
@col = col
|
10
|
-
@name = name
|
11
|
-
end
|
12
|
-
|
13
|
-
def == (other)
|
14
|
-
return false if other.nil?
|
15
|
-
( @buffer == other.buffer and @row == other.row and @col == other.col )
|
16
|
-
end
|
17
|
-
|
18
|
-
def <=> (other)
|
19
|
-
return nil if other.nil?
|
20
|
-
comparison = ( $diakonos.bufferToNumber( @buffer ) <=> $diakonos.bufferToNumber( other.buffer ) )
|
21
|
-
return comparison if comparison != 0
|
22
|
-
comparison = ( @row <=> other.row )
|
23
|
-
return comparison if comparison != 0
|
24
|
-
@col <=> other.col
|
25
|
-
end
|
26
|
-
|
27
|
-
def < (other)
|
28
|
-
( ( self <=> other ) < 0 )
|
29
|
-
end
|
30
|
-
def > (other)
|
31
|
-
( ( self <=> other ) > 0 )
|
32
|
-
end
|
33
|
-
|
34
|
-
def incRow( increment )
|
35
|
-
row += increment
|
36
|
-
end
|
37
|
-
def incCol( increment )
|
38
|
-
col += increment
|
39
|
-
end
|
40
|
-
def shift( row_inc, col_inc )
|
41
|
-
row += row_inc
|
42
|
-
col += col_inc
|
43
|
-
end
|
44
|
-
|
45
|
-
def to_s
|
46
|
-
"[#{@name}|#{@buffer.name}:#{@row+1},#{@col+1}]"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
data/lib/diakonos/buffer-hash.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
# A Hash which is iterated in insertion order.
|
2
|
-
# Keys are assumed to be paths; these paths are expanded on read and write.
|
3
|
-
class BufferHash < Hash
|
4
|
-
def initialize
|
5
|
-
@keys_ = []
|
6
|
-
end
|
7
|
-
|
8
|
-
def [] ( key )
|
9
|
-
super File.expand_path( key.to_s )
|
10
|
-
end
|
11
|
-
|
12
|
-
def []= ( key, value )
|
13
|
-
key = File.expand_path( key.to_s )
|
14
|
-
if not @keys_.include?( key )
|
15
|
-
@keys_ << key
|
16
|
-
end
|
17
|
-
super key, value
|
18
|
-
end
|
19
|
-
|
20
|
-
def each
|
21
|
-
@keys_.each do |key|
|
22
|
-
yield key, self[ key ]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def each_key
|
27
|
-
@keys_.each do |key|
|
28
|
-
yield key
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def each_value
|
33
|
-
@keys_.each do |key|
|
34
|
-
yield self[ key ]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def clear
|
39
|
-
@keys_ = []
|
40
|
-
super
|
41
|
-
end
|
42
|
-
|
43
|
-
def delete( key )
|
44
|
-
@keys_.delete key
|
45
|
-
super
|
46
|
-
end
|
47
|
-
|
48
|
-
def keys
|
49
|
-
@keys_.dup
|
50
|
-
end
|
51
|
-
|
52
|
-
def values
|
53
|
-
@keys_.map { |key| self[ key ] }
|
54
|
-
end
|
55
|
-
|
56
|
-
def length
|
57
|
-
@keys_.length
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module Diakonos
|
2
|
-
class Diakonos
|
3
|
-
attr_reader :current_buffer
|
4
|
-
|
5
|
-
def switchTo( buffer )
|
6
|
-
switched = false
|
7
|
-
if buffer
|
8
|
-
@buffer_stack -= [ @current_buffer ]
|
9
|
-
if @current_buffer
|
10
|
-
@buffer_stack.push @current_buffer
|
11
|
-
end
|
12
|
-
@current_buffer = buffer
|
13
|
-
runHookProcs( :after_buffer_switch, buffer )
|
14
|
-
updateStatusLine
|
15
|
-
updateContextLine
|
16
|
-
buffer.display
|
17
|
-
switched = true
|
18
|
-
end
|
19
|
-
|
20
|
-
switched
|
21
|
-
end
|
22
|
-
protected :switchTo
|
23
|
-
|
24
|
-
def remember_buffer( buffer )
|
25
|
-
if @buffer_history.last != buffer
|
26
|
-
@buffer_history << buffer
|
27
|
-
@buffer_history_pointer = @buffer_history.size - 1
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# The given buffer_number should be 1-based, not zero-based.
|
32
|
-
# Returns nil if no such buffer exists.
|
33
|
-
def bufferNumberToName( buffer_number )
|
34
|
-
return nil if buffer_number < 1
|
35
|
-
|
36
|
-
number = 1
|
37
|
-
buffer_name = nil
|
38
|
-
@buffers.each_key do |name|
|
39
|
-
if number == buffer_number
|
40
|
-
buffer_name = name
|
41
|
-
break
|
42
|
-
end
|
43
|
-
number += 1
|
44
|
-
end
|
45
|
-
buffer_name
|
46
|
-
end
|
47
|
-
|
48
|
-
# The returned value is 1-based, not zero-based.
|
49
|
-
# Returns nil if no such buffer exists.
|
50
|
-
def bufferToNumber( buffer )
|
51
|
-
number = 1
|
52
|
-
buffer_number = nil
|
53
|
-
@buffers.each_value do |b|
|
54
|
-
if b == buffer
|
55
|
-
buffer_number = number
|
56
|
-
break
|
57
|
-
end
|
58
|
-
number += 1
|
59
|
-
end
|
60
|
-
buffer_number
|
61
|
-
end
|
62
|
-
|
63
|
-
def show_buffer_file_diff( buffer = @current_buffer )
|
64
|
-
current_text_file = @diakonos_home + '/current-buffer'
|
65
|
-
buffer.saveCopy( current_text_file )
|
66
|
-
`#{@settings[ 'diff_command' ]} #{current_text_file} #{buffer.name} > #{@diff_filename}`
|
67
|
-
diff_buffer = openFile( @diff_filename )
|
68
|
-
yield diff_buffer
|
69
|
-
closeFile diff_buffer
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
data/lib/diakonos/buffer.rb
DELETED
@@ -1,2044 +0,0 @@
|
|
1
|
-
module Diakonos
|
2
|
-
|
3
|
-
class Buffer
|
4
|
-
attr_reader :name, :key, :original_language, :changing_selection, :read_only,
|
5
|
-
:last_col, :last_row, :tab_size, :last_screen_x, :last_screen_y, :last_screen_col
|
6
|
-
attr_writer :desired_column, :read_only
|
7
|
-
|
8
|
-
SELECTION = 0
|
9
|
-
TYPING = true
|
10
|
-
STOPPED_TYPING = true
|
11
|
-
STILL_TYPING = false
|
12
|
-
NO_SNAPSHOT = true
|
13
|
-
DO_DISPLAY = true
|
14
|
-
DONT_DISPLAY = false
|
15
|
-
READ_ONLY = true
|
16
|
-
READ_WRITE = false
|
17
|
-
ROUND_DOWN = false
|
18
|
-
ROUND_UP = true
|
19
|
-
PAD_END = true
|
20
|
-
DONT_PAD_END = false
|
21
|
-
MATCH_CLOSE = true
|
22
|
-
MATCH_ANY = false
|
23
|
-
START_FROM_BEGINNING = -1
|
24
|
-
DO_PITCH_CURSOR = true
|
25
|
-
DONT_PITCH_CURSOR = false
|
26
|
-
CLEAR_STACK_POINTER = true
|
27
|
-
DONT_CLEAR_STACK_POINTER = false
|
28
|
-
STRIP_LINE = true
|
29
|
-
DONT_STRIP_LINE = false
|
30
|
-
|
31
|
-
# Set name to nil to create a buffer that is not associated with a file.
|
32
|
-
def initialize( diakonos, name, key, read_only = false )
|
33
|
-
@diakonos = diakonos
|
34
|
-
@name = name
|
35
|
-
@key = key
|
36
|
-
@modified = false
|
37
|
-
@last_modification_check = Time.now
|
38
|
-
|
39
|
-
@buffer_states = Array.new
|
40
|
-
@cursor_states = Array.new
|
41
|
-
if @name
|
42
|
-
@name = @name.subHome
|
43
|
-
if FileTest.exists? @name
|
44
|
-
@lines = IO.readlines( @name )
|
45
|
-
if ( @lines.length == 0 ) or ( @lines[ -1 ][ -1..-1 ] == "\n" )
|
46
|
-
@lines.push ""
|
47
|
-
end
|
48
|
-
@lines = @lines.collect do |line|
|
49
|
-
line.chomp
|
50
|
-
end
|
51
|
-
else
|
52
|
-
@lines = Array.new
|
53
|
-
@lines[ 0 ] = ""
|
54
|
-
end
|
55
|
-
else
|
56
|
-
@lines = Array.new
|
57
|
-
@lines[ 0 ] = ""
|
58
|
-
end
|
59
|
-
@current_buffer_state = 0
|
60
|
-
|
61
|
-
@top_line = 0
|
62
|
-
@left_column = 0
|
63
|
-
@desired_column = 0
|
64
|
-
@mark_anchor = nil
|
65
|
-
@text_marks = Array.new
|
66
|
-
@last_search_regexps = nil
|
67
|
-
@highlight_regexp = nil
|
68
|
-
@last_search = nil
|
69
|
-
@changing_selection = false
|
70
|
-
@typing = false
|
71
|
-
@last_col = 0
|
72
|
-
@last_screen_col = 0
|
73
|
-
@last_screen_y = 0
|
74
|
-
@last_screen_x = 0
|
75
|
-
@last_row = 0
|
76
|
-
@read_only = read_only
|
77
|
-
@bookmarks = Array.new
|
78
|
-
@lang_stack = Array.new
|
79
|
-
@cursor_stack = Array.new
|
80
|
-
@cursor_stack_pointer = nil
|
81
|
-
|
82
|
-
configure
|
83
|
-
|
84
|
-
if @settings[ "convert_tabs" ]
|
85
|
-
tabs_subbed = false
|
86
|
-
@lines.collect! do |line|
|
87
|
-
new_line = line.expandTabs( @tab_size )
|
88
|
-
tabs_subbed = ( tabs_subbed or new_line != line )
|
89
|
-
# Return value for collect:
|
90
|
-
new_line
|
91
|
-
end
|
92
|
-
@modified = ( @modified or tabs_subbed )
|
93
|
-
if tabs_subbed
|
94
|
-
@diakonos.setILine "(spaces substituted for tab characters)"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
@buffer_states[ @current_buffer_state ] = @lines
|
99
|
-
@cursor_states[ @current_buffer_state ] = [ @last_row, @last_col ]
|
100
|
-
end
|
101
|
-
|
102
|
-
def configure(
|
103
|
-
language = (
|
104
|
-
@diakonos.getLanguageFromShaBang( @lines[ 0 ] ) or
|
105
|
-
@diakonos.getLanguageFromName( @name ) or
|
106
|
-
LANG_TEXT
|
107
|
-
)
|
108
|
-
)
|
109
|
-
reset_win_main
|
110
|
-
setLanguage language
|
111
|
-
@original_language = @language
|
112
|
-
end
|
113
|
-
|
114
|
-
def reset_win_main
|
115
|
-
@win_main = @diakonos.win_main
|
116
|
-
end
|
117
|
-
|
118
|
-
def setLanguage( language )
|
119
|
-
@settings = @diakonos.settings
|
120
|
-
@language = language
|
121
|
-
@token_regexps = ( @diakonos.token_regexps[ @language ] or Hash.new )
|
122
|
-
@close_token_regexps = ( @diakonos.close_token_regexps[ @language ] or Hash.new )
|
123
|
-
@token_formats = ( @diakonos.token_formats[ @language ] or Hash.new )
|
124
|
-
@indenters = @diakonos.indenters[ @language ]
|
125
|
-
@unindenters = @diakonos.unindenters[ @language ]
|
126
|
-
@preventers = @settings[ "lang.#{@language}.indent.preventers" ]
|
127
|
-
@closers = @diakonos.closers[ @language ] || Hash.new
|
128
|
-
@auto_indent = @settings[ "lang.#{@language}.indent.auto" ]
|
129
|
-
@indent_size = ( @settings[ "lang.#{@language}.indent.size" ] or 4 )
|
130
|
-
@indent_roundup = @settings[ "lang.#{@language}.indent.roundup" ].nil? ? true : @settings[ "lang.#{@language}.indent.roundup" ]
|
131
|
-
@indent_closers = @settings[ "lang.#{@language}.indent.closers" ].nil? ? false : @settings[ "lang.#{@language}.indent.closers" ]
|
132
|
-
@default_formatting = ( @settings[ "lang.#{@language}.format.default" ] or Curses::A_NORMAL )
|
133
|
-
@selection_formatting = ( @settings[ "lang.#{@language}.format.selection" ] or Curses::A_REVERSE )
|
134
|
-
@indent_ignore_charset = ( @settings[ "lang.#{@language}.indent.ignore.charset" ] or "" )
|
135
|
-
@tab_size = ( @settings[ "lang.#{@language}.tabsize" ] or DEFAULT_TAB_SIZE )
|
136
|
-
end
|
137
|
-
protected :setLanguage
|
138
|
-
|
139
|
-
def [] ( arg )
|
140
|
-
@lines[ arg ]
|
141
|
-
end
|
142
|
-
|
143
|
-
def == (other)
|
144
|
-
return false if other.nil?
|
145
|
-
key == other.key
|
146
|
-
end
|
147
|
-
|
148
|
-
def length
|
149
|
-
@lines.length
|
150
|
-
end
|
151
|
-
|
152
|
-
def modified?
|
153
|
-
@modified
|
154
|
-
end
|
155
|
-
|
156
|
-
def nice_name
|
157
|
-
@name || @settings[ "status.unnamed_str" ]
|
158
|
-
end
|
159
|
-
|
160
|
-
def display
|
161
|
-
return if not @diakonos.do_display
|
162
|
-
|
163
|
-
Thread.new do
|
164
|
-
#if $profiling
|
165
|
-
#RubyProf.start
|
166
|
-
#end
|
167
|
-
|
168
|
-
if @diakonos.display_mutex.try_lock
|
169
|
-
begin
|
170
|
-
Curses::curs_set 0
|
171
|
-
|
172
|
-
@continued_format_class = nil
|
173
|
-
|
174
|
-
@pen_down = true
|
175
|
-
|
176
|
-
# First, we have to "draw" off-screen, in order to check for opening of
|
177
|
-
# multi-line highlights.
|
178
|
-
|
179
|
-
# So, first look backwards from the @top_line to find the first opening
|
180
|
-
# regexp match, if any.
|
181
|
-
index = @top_line - 1
|
182
|
-
@lines[ [ 0, @top_line - @settings[ "view.lookback" ] ].max...@top_line ].reverse_each do |line|
|
183
|
-
open_index = -1
|
184
|
-
open_token_class = nil
|
185
|
-
open_match_text = nil
|
186
|
-
|
187
|
-
open_index, open_token_class, open_match_text = findOpeningMatch( line )
|
188
|
-
|
189
|
-
if open_token_class
|
190
|
-
@pen_down = false
|
191
|
-
@lines[ index...@top_line ].each do |line|
|
192
|
-
printLine line
|
193
|
-
end
|
194
|
-
@pen_down = true
|
195
|
-
|
196
|
-
break
|
197
|
-
end
|
198
|
-
|
199
|
-
index = index - 1
|
200
|
-
end
|
201
|
-
|
202
|
-
# Draw each on-screen line.
|
203
|
-
y = 0
|
204
|
-
@lines[ @top_line...(@diakonos.main_window_height + @top_line) ].each_with_index do |line, row|
|
205
|
-
@win_main.setpos( y, 0 )
|
206
|
-
printLine line.expandTabs( @tab_size )
|
207
|
-
@win_main.setpos( y, 0 )
|
208
|
-
paintMarks @top_line + row
|
209
|
-
y += 1
|
210
|
-
end
|
211
|
-
|
212
|
-
# Paint the empty space below the file if the file is too short to fit in one screen.
|
213
|
-
( y...@diakonos.main_window_height ).each do |y|
|
214
|
-
@win_main.setpos( y, 0 )
|
215
|
-
@win_main.attrset @default_formatting
|
216
|
-
linestr = " " * Curses::cols
|
217
|
-
if @settings[ "view.nonfilelines.visible" ]
|
218
|
-
linestr[ 0 ] = ( @settings[ "view.nonfilelines.character" ] or "~" )
|
219
|
-
end
|
220
|
-
|
221
|
-
@win_main.addstr linestr
|
222
|
-
end
|
223
|
-
|
224
|
-
@win_main.setpos( @last_screen_y , @last_screen_x )
|
225
|
-
@win_main.refresh
|
226
|
-
|
227
|
-
if @language != @original_language
|
228
|
-
setLanguage( @original_language )
|
229
|
-
end
|
230
|
-
|
231
|
-
Curses::curs_set 1
|
232
|
-
rescue Exception => e
|
233
|
-
@diakonos.log( "Display Exception:" )
|
234
|
-
@diakonos.log( e.message )
|
235
|
-
@diakonos.log( e.backtrace.join( "\n" ) )
|
236
|
-
showException e
|
237
|
-
end
|
238
|
-
@diakonos.display_mutex.unlock
|
239
|
-
@diakonos.displayDequeue
|
240
|
-
else
|
241
|
-
@diakonos.displayEnqueue( self )
|
242
|
-
end
|
243
|
-
|
244
|
-
#if $profiling
|
245
|
-
#result = RubyProf.stop
|
246
|
-
#printer = RubyProf::GraphHtmlPrinter.new( result )
|
247
|
-
#File.open( "#{ENV['HOME']}/svn/diakonos/profiling/diakonos-profile-#{Time.now.to_i}.html", 'w' ) do |f|
|
248
|
-
#printer.print( f )
|
249
|
-
#end
|
250
|
-
#end
|
251
|
-
end
|
252
|
-
|
253
|
-
end
|
254
|
-
|
255
|
-
def findOpeningMatch( line, match_close = true, bos_allowed = true )
|
256
|
-
open_index = line.length
|
257
|
-
open_token_class = nil
|
258
|
-
open_match_text = nil
|
259
|
-
match = nil
|
260
|
-
match_text = nil
|
261
|
-
@token_regexps.each do |token_class,regexp|
|
262
|
-
if match = regexp.match( line )
|
263
|
-
if match.length > 1
|
264
|
-
index = match.begin 1
|
265
|
-
match_text = match[ 1 ]
|
266
|
-
whole_match_index = match.begin 0
|
267
|
-
else
|
268
|
-
whole_match_index = index = match.begin( 0 )
|
269
|
-
match_text = match[ 0 ]
|
270
|
-
end
|
271
|
-
if ( not regexp.uses_bos ) or ( bos_allowed and ( whole_match_index == 0 ) )
|
272
|
-
if index < open_index
|
273
|
-
if ( ( not match_close ) or @close_token_regexps[ token_class ] )
|
274
|
-
open_index = index
|
275
|
-
open_token_class = token_class
|
276
|
-
open_match_text = match_text
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
[ open_index, open_token_class, open_match_text ]
|
284
|
-
end
|
285
|
-
|
286
|
-
def findClosingMatch( line_, regexp, bos_allowed = true, start_at = 0 )
|
287
|
-
close_match_text = nil
|
288
|
-
close_index = nil
|
289
|
-
if start_at > 0
|
290
|
-
line = line_[ start_at..-1 ]
|
291
|
-
else
|
292
|
-
line = line_
|
293
|
-
end
|
294
|
-
line.scan( regexp ) do |m|
|
295
|
-
match = Regexp.last_match
|
296
|
-
if match.length > 1
|
297
|
-
index = match.begin 1
|
298
|
-
match_text = match[ 1 ]
|
299
|
-
else
|
300
|
-
index = match.begin 0
|
301
|
-
match_text = match[ 0 ]
|
302
|
-
end
|
303
|
-
if ( not regexp.uses_bos ) or ( bos_allowed and ( index == 0 ) )
|
304
|
-
close_index = index
|
305
|
-
close_match_text = match_text
|
306
|
-
break
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
[ close_index, close_match_text ]
|
311
|
-
end
|
312
|
-
protected :findClosingMatch
|
313
|
-
|
314
|
-
# @mark_start[ "col" ] is inclusive,
|
315
|
-
# @mark_end[ "col" ] is exclusive.
|
316
|
-
def recordMarkStartAndEnd
|
317
|
-
if @mark_anchor
|
318
|
-
crow = @last_row
|
319
|
-
ccol = @last_col
|
320
|
-
anchor_first = true
|
321
|
-
if crow < @mark_anchor[ "row" ]
|
322
|
-
anchor_first = false
|
323
|
-
elsif crow > @mark_anchor[ "row" ]
|
324
|
-
anchor_first = true
|
325
|
-
else
|
326
|
-
if ccol < @mark_anchor[ "col" ]
|
327
|
-
anchor_first = false
|
328
|
-
end
|
329
|
-
end
|
330
|
-
if anchor_first
|
331
|
-
@text_marks[ SELECTION ] = TextMark.new(
|
332
|
-
@mark_anchor[ "row" ],
|
333
|
-
@mark_anchor[ "col" ],
|
334
|
-
crow,
|
335
|
-
ccol,
|
336
|
-
@selection_formatting
|
337
|
-
)
|
338
|
-
else
|
339
|
-
@text_marks[ SELECTION ] = TextMark.new(
|
340
|
-
crow,
|
341
|
-
ccol,
|
342
|
-
@mark_anchor[ "row" ],
|
343
|
-
@mark_anchor[ "col" ],
|
344
|
-
@selection_formatting
|
345
|
-
)
|
346
|
-
end
|
347
|
-
else
|
348
|
-
@text_marks[ SELECTION ] = nil
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
def selection_mark
|
353
|
-
@text_marks[ SELECTION ]
|
354
|
-
end
|
355
|
-
def selecting?
|
356
|
-
!!selection_mark
|
357
|
-
end
|
358
|
-
|
359
|
-
def select_current_line
|
360
|
-
@text_marks[ SELECTION ] = TextMark.new(
|
361
|
-
@last_row,
|
362
|
-
0,
|
363
|
-
@last_row,
|
364
|
-
@lines[ @last_row ].size,
|
365
|
-
@selection_formatting
|
366
|
-
)
|
367
|
-
@lines[ @last_row ]
|
368
|
-
end
|
369
|
-
|
370
|
-
def select_all
|
371
|
-
anchorSelection( 0, 0, DONT_DISPLAY )
|
372
|
-
cursorTo( @lines.length - 1, @lines[ -1 ].length, DO_DISPLAY )
|
373
|
-
end
|
374
|
-
|
375
|
-
def select( from_regexp, to_regexp, include_ending = true )
|
376
|
-
start_row = nil
|
377
|
-
|
378
|
-
@lines[ 0..@last_row ].reverse.each_with_index do |line,index|
|
379
|
-
if line =~ from_regexp
|
380
|
-
start_row = @last_row - index
|
381
|
-
break
|
382
|
-
end
|
383
|
-
end
|
384
|
-
if start_row
|
385
|
-
end_row = nil
|
386
|
-
@lines[ start_row..-1 ].each_with_index do |line,index|
|
387
|
-
if line =~ to_regexp
|
388
|
-
end_row = start_row + index
|
389
|
-
break
|
390
|
-
end
|
391
|
-
end
|
392
|
-
if end_row
|
393
|
-
if include_ending
|
394
|
-
end_row += 1
|
395
|
-
end
|
396
|
-
anchorSelection( start_row, 0, DONT_DISPLAY )
|
397
|
-
cursorTo( end_row, 0 )
|
398
|
-
display
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
# Prints text to the screen, truncating where necessary.
|
404
|
-
# Returns nil if the string is completely off-screen.
|
405
|
-
# write_cursor_col is buffer-relative, not screen-relative
|
406
|
-
def truncateOffScreen( string, write_cursor_col )
|
407
|
-
retval = string
|
408
|
-
|
409
|
-
# Truncate based on left edge of display area
|
410
|
-
if write_cursor_col < @left_column
|
411
|
-
retval = retval[ (@left_column - write_cursor_col)..-1 ]
|
412
|
-
write_cursor_col = @left_column
|
413
|
-
end
|
414
|
-
|
415
|
-
if retval
|
416
|
-
# Truncate based on right edge of display area
|
417
|
-
if write_cursor_col + retval.length > @left_column + Curses::cols - 1
|
418
|
-
new_length = ( @left_column + Curses::cols - write_cursor_col )
|
419
|
-
if new_length <= 0
|
420
|
-
retval = nil
|
421
|
-
else
|
422
|
-
retval = retval[ 0...new_length ]
|
423
|
-
end
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
retval == "" ? nil : retval
|
428
|
-
end
|
429
|
-
|
430
|
-
# For debugging purposes
|
431
|
-
def quotedOrNil( str )
|
432
|
-
if str.nil?
|
433
|
-
"nil"
|
434
|
-
else
|
435
|
-
"'#{str}'"
|
436
|
-
end
|
437
|
-
end
|
438
|
-
|
439
|
-
def paintMarks( row )
|
440
|
-
string = @lines[ row ][ @left_column ... @left_column + Curses::cols ]
|
441
|
-
return if string.nil? or string == ""
|
442
|
-
string = string.expandTabs( @tab_size )
|
443
|
-
cury = @win_main.cury
|
444
|
-
curx = @win_main.curx
|
445
|
-
|
446
|
-
@text_marks.reverse_each do |text_mark|
|
447
|
-
if text_mark
|
448
|
-
@win_main.attrset text_mark.formatting
|
449
|
-
if ( (text_mark.start_row + 1) .. (text_mark.end_row - 1) ) === row
|
450
|
-
@win_main.setpos( cury, curx )
|
451
|
-
@win_main.addstr string
|
452
|
-
elsif row == text_mark.start_row and row == text_mark.end_row
|
453
|
-
expanded_col = tabExpandedColumn( text_mark.start_col, row )
|
454
|
-
if expanded_col < @left_column + Curses::cols
|
455
|
-
left = [ expanded_col - @left_column, 0 ].max
|
456
|
-
right = tabExpandedColumn( text_mark.end_col, row ) - @left_column
|
457
|
-
if left < right
|
458
|
-
@win_main.setpos( cury, curx + left )
|
459
|
-
@win_main.addstr string[ left...right ]
|
460
|
-
end
|
461
|
-
end
|
462
|
-
elsif row == text_mark.start_row
|
463
|
-
expanded_col = tabExpandedColumn( text_mark.start_col, row )
|
464
|
-
if expanded_col < @left_column + Curses::cols
|
465
|
-
left = [ expanded_col - @left_column, 0 ].max
|
466
|
-
@win_main.setpos( cury, curx + left )
|
467
|
-
@win_main.addstr string[ left..-1 ]
|
468
|
-
end
|
469
|
-
elsif row == text_mark.end_row
|
470
|
-
right = tabExpandedColumn( text_mark.end_col, row ) - @left_column
|
471
|
-
@win_main.setpos( cury, curx )
|
472
|
-
@win_main.addstr string[ 0...right ]
|
473
|
-
else
|
474
|
-
# This row not in selection.
|
475
|
-
end
|
476
|
-
end
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
|
-
def printString( string, formatting = ( @token_formats[ @continued_format_class ] or @default_formatting ) )
|
481
|
-
return if not @pen_down
|
482
|
-
return if string.nil?
|
483
|
-
|
484
|
-
@win_main.attrset formatting
|
485
|
-
@win_main.addstr string
|
486
|
-
end
|
487
|
-
|
488
|
-
# This method assumes that the cursor has been setup already at
|
489
|
-
# the left-most column of the correct on-screen row.
|
490
|
-
# It merely unintelligently prints the characters on the current curses line,
|
491
|
-
# refusing to print characters of the in-buffer line which are offscreen.
|
492
|
-
def printLine( line )
|
493
|
-
i = 0
|
494
|
-
substr = nil
|
495
|
-
index = nil
|
496
|
-
while i < line.length
|
497
|
-
substr = line[ i..-1 ]
|
498
|
-
if @continued_format_class
|
499
|
-
close_index, close_match_text = findClosingMatch( substr, @close_token_regexps[ @continued_format_class ], i == 0 )
|
500
|
-
|
501
|
-
if close_match_text.nil?
|
502
|
-
printString truncateOffScreen( substr, i )
|
503
|
-
printPaddingFrom( line.length )
|
504
|
-
i = line.length
|
505
|
-
else
|
506
|
-
end_index = close_index + close_match_text.length
|
507
|
-
printString truncateOffScreen( substr[ 0...end_index ], i )
|
508
|
-
@continued_format_class = nil
|
509
|
-
i += end_index
|
510
|
-
end
|
511
|
-
else
|
512
|
-
first_index, first_token_class, first_word = findOpeningMatch( substr, MATCH_ANY, i == 0 )
|
513
|
-
|
514
|
-
if @lang_stack.length > 0
|
515
|
-
prev_lang, close_token_class = @lang_stack[ -1 ]
|
516
|
-
close_index, close_match_text = findClosingMatch( substr, @diakonos.close_token_regexps[ prev_lang ][ close_token_class ], i == 0 )
|
517
|
-
if close_match_text and close_index <= first_index
|
518
|
-
if close_index > 0
|
519
|
-
# Print any remaining text in the embedded language
|
520
|
-
printString truncateOffScreen( substr[ 0...close_index ], i )
|
521
|
-
i += substr[ 0...close_index ].length
|
522
|
-
end
|
523
|
-
|
524
|
-
@lang_stack.pop
|
525
|
-
setLanguage prev_lang
|
526
|
-
|
527
|
-
printString(
|
528
|
-
truncateOffScreen( substr[ close_index...(close_index + close_match_text.length) ], i ),
|
529
|
-
@token_formats[ close_token_class ]
|
530
|
-
)
|
531
|
-
i += close_match_text.length
|
532
|
-
|
533
|
-
# Continue printing from here.
|
534
|
-
next
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
if first_word
|
539
|
-
if first_index > 0
|
540
|
-
# Print any preceding text in the default format
|
541
|
-
printString truncateOffScreen( substr[ 0...first_index ], i )
|
542
|
-
i += substr[ 0...first_index ].length
|
543
|
-
end
|
544
|
-
printString( truncateOffScreen( first_word, i ), @token_formats[ first_token_class ] )
|
545
|
-
i += first_word.length
|
546
|
-
if @close_token_regexps[ first_token_class ]
|
547
|
-
if change_to = @settings[ "lang.#{@language}.tokens.#{first_token_class}.change_to" ]
|
548
|
-
@lang_stack.push [ @language, first_token_class ]
|
549
|
-
setLanguage change_to
|
550
|
-
else
|
551
|
-
@continued_format_class = first_token_class
|
552
|
-
end
|
553
|
-
end
|
554
|
-
else
|
555
|
-
printString truncateOffScreen( substr, i )
|
556
|
-
i += substr.length
|
557
|
-
break
|
558
|
-
end
|
559
|
-
end
|
560
|
-
end
|
561
|
-
|
562
|
-
printPaddingFrom i
|
563
|
-
end
|
564
|
-
|
565
|
-
def printPaddingFrom( col )
|
566
|
-
return if not @pen_down
|
567
|
-
|
568
|
-
if col < @left_column
|
569
|
-
remainder = Curses::cols
|
570
|
-
else
|
571
|
-
remainder = @left_column + Curses::cols - col
|
572
|
-
end
|
573
|
-
|
574
|
-
if remainder > 0
|
575
|
-
printString( " " * remainder )
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
def save( filename = nil, prompt_overwrite = DONT_PROMPT_OVERWRITE )
|
580
|
-
if filename
|
581
|
-
name = filename.subHome
|
582
|
-
else
|
583
|
-
name = @name
|
584
|
-
end
|
585
|
-
|
586
|
-
if @read_only and FileTest.exists?( @name ) and FileTest.exists?( name ) and ( File.stat( @name ).ino == File.stat( name ).ino )
|
587
|
-
@diakonos.setILine "#{name} cannot be saved since it is read-only."
|
588
|
-
else
|
589
|
-
@read_only = false
|
590
|
-
if name.nil?
|
591
|
-
@diakonos.saveFileAs
|
592
|
-
else
|
593
|
-
proceed = true
|
594
|
-
|
595
|
-
if prompt_overwrite and FileTest.exists? name
|
596
|
-
proceed = false
|
597
|
-
choice = @diakonos.getChoice(
|
598
|
-
"Overwrite existing '#{name}'?",
|
599
|
-
[ CHOICE_YES, CHOICE_NO ],
|
600
|
-
CHOICE_NO
|
601
|
-
)
|
602
|
-
case choice
|
603
|
-
when CHOICE_YES
|
604
|
-
proceed = true
|
605
|
-
when CHOICE_NO
|
606
|
-
proceed = false
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
if file_modified?
|
611
|
-
proceed = ! @diakonos.revert( "File has been altered externally. Load on-disk version?" )
|
612
|
-
end
|
613
|
-
|
614
|
-
if proceed
|
615
|
-
File.open( name, "w" ) do |f|
|
616
|
-
@lines[ 0..-2 ].each do |line|
|
617
|
-
if @settings[ 'strip_trailing_whitespace_on_save' ]
|
618
|
-
line.rstrip!
|
619
|
-
end
|
620
|
-
f.puts line
|
621
|
-
end
|
622
|
-
|
623
|
-
line = @lines[ -1 ]
|
624
|
-
if @settings[ 'strip_trailing_whitespace_on_save' ]
|
625
|
-
line.rstrip!
|
626
|
-
end
|
627
|
-
if line != ""
|
628
|
-
# No final newline character
|
629
|
-
f.print line
|
630
|
-
f.print "\n" if @settings[ "eof_newline" ]
|
631
|
-
end
|
632
|
-
|
633
|
-
if @settings[ 'strip_trailing_whitespace_on_save' ]
|
634
|
-
if @last_col > @lines[ @last_row ].size
|
635
|
-
cursorTo @last_row, @lines[ @last_row ].size
|
636
|
-
end
|
637
|
-
end
|
638
|
-
end
|
639
|
-
@name = name
|
640
|
-
@last_modification_check = File.mtime( @name )
|
641
|
-
saved = true
|
642
|
-
|
643
|
-
if @name == @diakonos.diakonos_conf
|
644
|
-
@diakonos.loadConfiguration
|
645
|
-
@diakonos.initializeDisplay
|
646
|
-
end
|
647
|
-
|
648
|
-
@modified = false
|
649
|
-
|
650
|
-
display
|
651
|
-
@diakonos.updateStatusLine
|
652
|
-
end
|
653
|
-
end
|
654
|
-
end
|
655
|
-
|
656
|
-
saved
|
657
|
-
end
|
658
|
-
|
659
|
-
# Returns true on successful write.
|
660
|
-
def saveCopy( filename )
|
661
|
-
return false if filename.nil?
|
662
|
-
|
663
|
-
name = filename.subHome
|
664
|
-
|
665
|
-
File.open( name, "w" ) do |f|
|
666
|
-
@lines[ 0..-2 ].each do |line|
|
667
|
-
f.puts line
|
668
|
-
end
|
669
|
-
if @lines[ -1 ] != ""
|
670
|
-
# No final newline character
|
671
|
-
f.print @lines[ -1 ]
|
672
|
-
f.print "\n" if @settings[ "eof_newline" ]
|
673
|
-
end
|
674
|
-
end
|
675
|
-
|
676
|
-
true
|
677
|
-
end
|
678
|
-
|
679
|
-
def replaceChar( c )
|
680
|
-
row = @last_row
|
681
|
-
col = @last_col
|
682
|
-
takeSnapshot( TYPING )
|
683
|
-
@lines[ row ][ col ] = c
|
684
|
-
setModified
|
685
|
-
end
|
686
|
-
|
687
|
-
def insertChar( c )
|
688
|
-
row = @last_row
|
689
|
-
col = @last_col
|
690
|
-
takeSnapshot( TYPING )
|
691
|
-
line = @lines[ row ]
|
692
|
-
@lines[ row ] = line[ 0...col ] + c.chr + line[ col..-1 ]
|
693
|
-
setModified
|
694
|
-
end
|
695
|
-
|
696
|
-
def insertString( str )
|
697
|
-
row = @last_row
|
698
|
-
col = @last_col
|
699
|
-
takeSnapshot( TYPING )
|
700
|
-
line = @lines[ row ]
|
701
|
-
@lines[ row ] = line[ 0...col ] + str + line[ col..-1 ]
|
702
|
-
setModified
|
703
|
-
end
|
704
|
-
|
705
|
-
# x and y are given window-relative, not buffer-relative.
|
706
|
-
def delete
|
707
|
-
if selection_mark
|
708
|
-
deleteSelection
|
709
|
-
else
|
710
|
-
row = @last_row
|
711
|
-
col = @last_col
|
712
|
-
if ( row >= 0 ) and ( col >= 0 )
|
713
|
-
line = @lines[ row ]
|
714
|
-
if col == line.length
|
715
|
-
if row < @lines.length - 1
|
716
|
-
# Delete newline, and concat next line
|
717
|
-
joinLines( row )
|
718
|
-
cursorTo( @last_row, @last_col )
|
719
|
-
end
|
720
|
-
else
|
721
|
-
takeSnapshot( TYPING )
|
722
|
-
@lines[ row ] = line[ 0...col ] + line[ (col + 1)..-1 ]
|
723
|
-
setModified
|
724
|
-
end
|
725
|
-
end
|
726
|
-
end
|
727
|
-
end
|
728
|
-
|
729
|
-
def joinLines( row = @last_row, strip = DONT_STRIP_LINE )
|
730
|
-
takeSnapshot( TYPING )
|
731
|
-
next_line = @lines.delete_at( row + 1 )
|
732
|
-
if strip
|
733
|
-
next_line = ' ' + next_line.strip
|
734
|
-
end
|
735
|
-
@lines[ row ] << next_line
|
736
|
-
setModified
|
737
|
-
end
|
738
|
-
|
739
|
-
def close_code
|
740
|
-
line = @lines[ @last_row ]
|
741
|
-
@closers.each_value do |h|
|
742
|
-
h[ :regexp ] =~ line
|
743
|
-
lm = Regexp.last_match
|
744
|
-
if lm
|
745
|
-
str = h[ :closer ].call( lm ).to_s
|
746
|
-
r, c = @last_row, @last_col
|
747
|
-
paste str, @indent_closers
|
748
|
-
cursorTo r, c
|
749
|
-
if /%_/ === str
|
750
|
-
find( [ /%_/ ], :direction => :down, :replacement => '', :auto_choice => CHOICE_YES_AND_STOP )
|
751
|
-
end
|
752
|
-
else
|
753
|
-
@diakonos.log h[ :regexp ].inspect + " does not match '#{line}'"
|
754
|
-
end
|
755
|
-
end
|
756
|
-
end
|
757
|
-
|
758
|
-
def collapseWhitespace
|
759
|
-
if selection_mark
|
760
|
-
removeSelection DONT_DISPLAY
|
761
|
-
end
|
762
|
-
|
763
|
-
line = @lines[ @last_row ]
|
764
|
-
head = line[ 0...@last_col ]
|
765
|
-
tail = line[ @last_col..-1 ]
|
766
|
-
new_head = head.sub( /\s+$/, '' )
|
767
|
-
new_line = new_head + tail.sub( /^\s+/, ' ' )
|
768
|
-
if new_line != line
|
769
|
-
takeSnapshot( TYPING )
|
770
|
-
@lines[ @last_row ] = new_line
|
771
|
-
cursorTo( @last_row, @last_col - ( head.length - new_head.length ) )
|
772
|
-
setModified
|
773
|
-
end
|
774
|
-
end
|
775
|
-
|
776
|
-
def selected_lines
|
777
|
-
selection = selection_mark
|
778
|
-
if selection
|
779
|
-
if selection.end_col == 0
|
780
|
-
end_row = selection.end_row - 1
|
781
|
-
else
|
782
|
-
end_row = selection.end_row
|
783
|
-
end
|
784
|
-
@lines[ selection.start_row..end_row ]
|
785
|
-
else
|
786
|
-
[ @lines[ @last_row ] ]
|
787
|
-
end
|
788
|
-
end
|
789
|
-
|
790
|
-
def columnize( delimiter = /=>?|:|,/, num_spaces_padding = 1 )
|
791
|
-
takeSnapshot
|
792
|
-
|
793
|
-
lines = selected_lines
|
794
|
-
column_width = 0
|
795
|
-
lines.each do |line|
|
796
|
-
pos = ( line =~ delimiter )
|
797
|
-
if pos
|
798
|
-
column_width = [ pos, column_width ].max
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
802
|
-
padding = ' ' * num_spaces_padding
|
803
|
-
one_modified = false
|
804
|
-
|
805
|
-
lines.each do |line|
|
806
|
-
old_line = line.dup
|
807
|
-
if line =~ /^(.+?)(#{delimiter.source})(.*)$/
|
808
|
-
pre = $1
|
809
|
-
del = $2
|
810
|
-
post = $3
|
811
|
-
if pre !~ /\s$/
|
812
|
-
del = " #{del}"
|
813
|
-
end
|
814
|
-
if post !~ /^\s/
|
815
|
-
del = "#{del} "
|
816
|
-
end
|
817
|
-
del.sub!( /^\s+/, ' ' * num_spaces_padding )
|
818
|
-
del.sub!( /\s+$/, ' ' * num_spaces_padding )
|
819
|
-
line.replace( ( "%-#{column_width}s" % pre ) + del + post )
|
820
|
-
end
|
821
|
-
one_modified ||= ( line != old_line )
|
822
|
-
end
|
823
|
-
|
824
|
-
if one_modified
|
825
|
-
setModified
|
826
|
-
end
|
827
|
-
end
|
828
|
-
|
829
|
-
def comment_out
|
830
|
-
takeSnapshot
|
831
|
-
one_modified = false
|
832
|
-
selected_lines.each do |line|
|
833
|
-
old_line = line.dup
|
834
|
-
line.gsub!( /^(\s*)/, "\\1" + @settings[ "lang.#{@language}.comment_string" ].to_s )
|
835
|
-
line << @settings[ "lang.#{@language}.comment_close_string" ].to_s
|
836
|
-
one_modified ||= ( line != old_line )
|
837
|
-
end
|
838
|
-
if one_modified
|
839
|
-
setModified
|
840
|
-
end
|
841
|
-
end
|
842
|
-
|
843
|
-
def uncomment
|
844
|
-
takeSnapshot
|
845
|
-
comment_string = Regexp.escape( @settings[ "lang.#{@language}.comment_string" ].to_s )
|
846
|
-
comment_close_string = Regexp.escape( @settings[ "lang.#{@language}.comment_close_string" ].to_s )
|
847
|
-
one_modified = false
|
848
|
-
selected_lines.each do |line|
|
849
|
-
old_line = line.dup
|
850
|
-
line.gsub!( /^(\s*)#{comment_string}/, "\\1" )
|
851
|
-
line.gsub!( /#{comment_close_string}$/, '' )
|
852
|
-
one_modified ||= ( line != old_line )
|
853
|
-
end
|
854
|
-
if one_modified
|
855
|
-
setModified
|
856
|
-
end
|
857
|
-
end
|
858
|
-
|
859
|
-
def deleteLine
|
860
|
-
removeSelection( DONT_DISPLAY ) if selection_mark
|
861
|
-
|
862
|
-
row = @last_row
|
863
|
-
takeSnapshot
|
864
|
-
retval = nil
|
865
|
-
if @lines.length == 1
|
866
|
-
retval = @lines[ 0 ]
|
867
|
-
@lines[ 0 ] = ""
|
868
|
-
else
|
869
|
-
retval = @lines[ row ]
|
870
|
-
@lines.delete_at row
|
871
|
-
end
|
872
|
-
cursorTo( row, 0 )
|
873
|
-
setModified
|
874
|
-
|
875
|
-
retval
|
876
|
-
end
|
877
|
-
|
878
|
-
def deleteToEOL
|
879
|
-
removeSelection( DONT_DISPLAY ) if selection_mark
|
880
|
-
|
881
|
-
row = @last_row
|
882
|
-
col = @last_col
|
883
|
-
|
884
|
-
takeSnapshot
|
885
|
-
if @settings[ 'delete_newline_on_delete_to_eol' ] and col == @lines[ row ].size
|
886
|
-
next_line = @lines.delete_at( row + 1 )
|
887
|
-
@lines[ row ] << next_line
|
888
|
-
retval = ''
|
889
|
-
else
|
890
|
-
retval = [ @lines[ row ][ col..-1 ] ]
|
891
|
-
@lines[ row ] = @lines[ row ][ 0...col ]
|
892
|
-
end
|
893
|
-
setModified
|
894
|
-
|
895
|
-
retval
|
896
|
-
end
|
897
|
-
|
898
|
-
def delete_to( char )
|
899
|
-
removeSelection( DONT_DISPLAY ) if selection_mark
|
900
|
-
takeSnapshot
|
901
|
-
index = @lines[ @last_row ].index( char, @last_col )
|
902
|
-
if index
|
903
|
-
retval = @lines[ @last_row ].slice!( @last_col, index - @last_col )
|
904
|
-
setModified
|
905
|
-
retval
|
906
|
-
end
|
907
|
-
end
|
908
|
-
|
909
|
-
def delete_to_and_from( char )
|
910
|
-
removeSelection( DONT_DISPLAY ) if selection_mark
|
911
|
-
takeSnapshot
|
912
|
-
index_before = @lines[ @last_row ].rindex( char, @last_col )
|
913
|
-
index_after = @lines[ @last_row ].index( char, @last_col )
|
914
|
-
if index_before && index_after
|
915
|
-
index_before += 1
|
916
|
-
retval = @lines[ @last_row ].slice!( index_before, index_after - index_before )
|
917
|
-
cursorTo( @last_row, index_before )
|
918
|
-
setModified
|
919
|
-
retval
|
920
|
-
end
|
921
|
-
end
|
922
|
-
|
923
|
-
def carriageReturn
|
924
|
-
takeSnapshot
|
925
|
-
row = @last_row
|
926
|
-
col = @last_col
|
927
|
-
@lines = @lines[ 0...row ] +
|
928
|
-
[ @lines[ row ][ 0...col ] ] +
|
929
|
-
[ @lines[ row ][ col..-1 ] ] +
|
930
|
-
@lines[ (row+1)..-1 ]
|
931
|
-
cursorTo( row + 1, 0 )
|
932
|
-
parsedIndent if @auto_indent
|
933
|
-
setModified
|
934
|
-
end
|
935
|
-
|
936
|
-
def lineAt( y )
|
937
|
-
row = @top_line + y
|
938
|
-
if row < 0
|
939
|
-
nil
|
940
|
-
else
|
941
|
-
@lines[ row ]
|
942
|
-
end
|
943
|
-
end
|
944
|
-
|
945
|
-
def current_line
|
946
|
-
@lines[ @last_row ]
|
947
|
-
end
|
948
|
-
|
949
|
-
# Returns true iff the given column, x, is less than the length of the given line, y.
|
950
|
-
def inLine( x, y )
|
951
|
-
x + @left_column < lineAt( y ).length
|
952
|
-
end
|
953
|
-
|
954
|
-
# Translates the window column, x, to a buffer-relative column index.
|
955
|
-
def columnOf( x )
|
956
|
-
@left_column + x
|
957
|
-
end
|
958
|
-
|
959
|
-
# Translates the window row, y, to a buffer-relative row index.
|
960
|
-
def rowOf( y )
|
961
|
-
@top_line + y
|
962
|
-
end
|
963
|
-
|
964
|
-
# Returns nil if the row is off-screen.
|
965
|
-
def rowToY( row )
|
966
|
-
return nil if row.nil?
|
967
|
-
y = row - @top_line
|
968
|
-
y = nil if ( y < 0 ) or ( y > @top_line + @diakonos.main_window_height - 1 )
|
969
|
-
y
|
970
|
-
end
|
971
|
-
|
972
|
-
# Returns nil if the column is off-screen.
|
973
|
-
def columnToX( col )
|
974
|
-
return nil if col.nil?
|
975
|
-
x = col - @left_column
|
976
|
-
x = nil if ( x < 0 ) or ( x > @left_column + Curses::cols - 1 )
|
977
|
-
x
|
978
|
-
end
|
979
|
-
|
980
|
-
def currentRow
|
981
|
-
@last_row
|
982
|
-
end
|
983
|
-
|
984
|
-
def currentColumn
|
985
|
-
@last_col
|
986
|
-
end
|
987
|
-
|
988
|
-
# Returns the amount the view was actually panned.
|
989
|
-
def panView( x = 1, do_display = DO_DISPLAY )
|
990
|
-
old_left_column = @left_column
|
991
|
-
@left_column = [ @left_column + x, 0 ].max
|
992
|
-
recordMarkStartAndEnd
|
993
|
-
display if do_display
|
994
|
-
@left_column - old_left_column
|
995
|
-
end
|
996
|
-
|
997
|
-
# Returns the amount the view was actually pitched.
|
998
|
-
def pitchView( y = 1, do_pitch_cursor = DONT_PITCH_CURSOR, do_display = DO_DISPLAY )
|
999
|
-
old_top_line = @top_line
|
1000
|
-
new_top_line = @top_line + y
|
1001
|
-
|
1002
|
-
if new_top_line < 0
|
1003
|
-
@top_line = 0
|
1004
|
-
elsif new_top_line + @diakonos.main_window_height > @lines.length
|
1005
|
-
@top_line = [ @lines.length - @diakonos.main_window_height, 0 ].max
|
1006
|
-
else
|
1007
|
-
@top_line = new_top_line
|
1008
|
-
end
|
1009
|
-
|
1010
|
-
old_row = @last_row
|
1011
|
-
old_col = @last_col
|
1012
|
-
|
1013
|
-
changed = ( @top_line - old_top_line )
|
1014
|
-
if changed != 0 and do_pitch_cursor
|
1015
|
-
@last_row += changed
|
1016
|
-
end
|
1017
|
-
|
1018
|
-
height = [ @diakonos.main_window_height, @lines.length ].min
|
1019
|
-
|
1020
|
-
@last_row = @last_row.fit( @top_line, @top_line + height - 1 )
|
1021
|
-
if @last_row - @top_line < @settings[ "view.margin.y" ]
|
1022
|
-
@last_row = @top_line + @settings[ "view.margin.y" ]
|
1023
|
-
@last_row = @last_row.fit( @top_line, @top_line + height - 1 )
|
1024
|
-
elsif @top_line + height - 1 - @last_row < @settings[ "view.margin.y" ]
|
1025
|
-
@last_row = @top_line + height - 1 - @settings[ "view.margin.y" ]
|
1026
|
-
@last_row = @last_row.fit( @top_line, @top_line + height - 1 )
|
1027
|
-
end
|
1028
|
-
@last_col = @last_col.fit( @left_column, [ @left_column + Curses::cols - 1, @lines[ @last_row ].length ].min )
|
1029
|
-
@last_screen_y = @last_row - @top_line
|
1030
|
-
@last_screen_x = tabExpandedColumn( @last_col, @last_row ) - @left_column
|
1031
|
-
|
1032
|
-
recordMarkStartAndEnd
|
1033
|
-
|
1034
|
-
if changed != 0
|
1035
|
-
highlightMatches
|
1036
|
-
if @diakonos.there_was_non_movement
|
1037
|
-
pushCursorState( old_top_line, old_row, old_col )
|
1038
|
-
end
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
display if do_display
|
1042
|
-
|
1043
|
-
changed
|
1044
|
-
end
|
1045
|
-
|
1046
|
-
def pushCursorState( top_line, row, col, clear_stack_pointer = CLEAR_STACK_POINTER )
|
1047
|
-
new_state = {
|
1048
|
-
:top_line => top_line,
|
1049
|
-
:row => row,
|
1050
|
-
:col => col
|
1051
|
-
}
|
1052
|
-
if not @cursor_stack.include? new_state
|
1053
|
-
@cursor_stack << new_state
|
1054
|
-
if clear_stack_pointer
|
1055
|
-
@cursor_stack_pointer = nil
|
1056
|
-
end
|
1057
|
-
@diakonos.clearNonMovementFlag
|
1058
|
-
end
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
# Returns true iff the cursor changed positions in the buffer.
|
1062
|
-
def cursorTo( row, col, do_display = DONT_DISPLAY, stopped_typing = STOPPED_TYPING, adjust_row = ADJUST_ROW )
|
1063
|
-
old_last_row = @last_row
|
1064
|
-
old_last_col = @last_col
|
1065
|
-
|
1066
|
-
row = row.fit( 0, @lines.length - 1 )
|
1067
|
-
|
1068
|
-
if col < 0
|
1069
|
-
if adjust_row
|
1070
|
-
if row > 0
|
1071
|
-
row = row - 1
|
1072
|
-
col = @lines[ row ].length
|
1073
|
-
else
|
1074
|
-
col = 0
|
1075
|
-
end
|
1076
|
-
else
|
1077
|
-
col = 0
|
1078
|
-
end
|
1079
|
-
elsif col > @lines[ row ].length
|
1080
|
-
if adjust_row
|
1081
|
-
if row < @lines.length - 1
|
1082
|
-
row = row + 1
|
1083
|
-
col = 0
|
1084
|
-
else
|
1085
|
-
col = @lines[ row ].length
|
1086
|
-
end
|
1087
|
-
else
|
1088
|
-
col = @lines[ row ].length
|
1089
|
-
end
|
1090
|
-
end
|
1091
|
-
|
1092
|
-
if adjust_row
|
1093
|
-
@desired_column = col
|
1094
|
-
else
|
1095
|
-
goto_col = [ @desired_column, @lines[ row ].length ].min
|
1096
|
-
if col < goto_col
|
1097
|
-
col = goto_col
|
1098
|
-
end
|
1099
|
-
end
|
1100
|
-
|
1101
|
-
new_col = tabExpandedColumn( col, row )
|
1102
|
-
view_changed = showCharacter( row, new_col )
|
1103
|
-
@last_screen_y = row - @top_line
|
1104
|
-
@last_screen_x = new_col - @left_column
|
1105
|
-
|
1106
|
-
@typing = false if stopped_typing
|
1107
|
-
@last_row = row
|
1108
|
-
@last_col = col
|
1109
|
-
@last_screen_col = new_col
|
1110
|
-
changed = ( @last_row != old_last_row or @last_col != old_last_col )
|
1111
|
-
if changed
|
1112
|
-
recordMarkStartAndEnd
|
1113
|
-
|
1114
|
-
removed = false
|
1115
|
-
if not @changing_selection and selection_mark
|
1116
|
-
removeSelection( DONT_DISPLAY )
|
1117
|
-
removed = true
|
1118
|
-
end
|
1119
|
-
if removed or ( do_display and ( selection_mark or view_changed ) )
|
1120
|
-
display
|
1121
|
-
else
|
1122
|
-
@diakonos.display_mutex.synchronize do
|
1123
|
-
@win_main.setpos( @last_screen_y, @last_screen_x )
|
1124
|
-
end
|
1125
|
-
end
|
1126
|
-
@diakonos.updateStatusLine
|
1127
|
-
@diakonos.updateContextLine
|
1128
|
-
|
1129
|
-
@diakonos.remember_buffer self
|
1130
|
-
end
|
1131
|
-
|
1132
|
-
changed
|
1133
|
-
end
|
1134
|
-
|
1135
|
-
def cursorReturn( direction )
|
1136
|
-
delta = 0
|
1137
|
-
if @cursor_stack_pointer.nil?
|
1138
|
-
pushCursorState( @top_line, @last_row, @last_col, DONT_CLEAR_STACK_POINTER )
|
1139
|
-
delta = 1
|
1140
|
-
end
|
1141
|
-
case direction
|
1142
|
-
when :forward
|
1143
|
-
@cursor_stack_pointer = ( @cursor_stack_pointer || 0 ) + 1
|
1144
|
-
#when :backward
|
1145
|
-
else
|
1146
|
-
@cursor_stack_pointer = ( @cursor_stack_pointer || @cursor_stack.length ) - 1 - delta
|
1147
|
-
end
|
1148
|
-
|
1149
|
-
return_pointer = @cursor_stack_pointer
|
1150
|
-
|
1151
|
-
if @cursor_stack_pointer < 0
|
1152
|
-
return_pointer = @cursor_stack_pointer = 0
|
1153
|
-
elsif @cursor_stack_pointer >= @cursor_stack.length
|
1154
|
-
return_pointer = @cursor_stack_pointer = @cursor_stack.length - 1
|
1155
|
-
else
|
1156
|
-
cursor_state = @cursor_stack[ @cursor_stack_pointer ]
|
1157
|
-
if cursor_state
|
1158
|
-
pitchView( cursor_state[ :top_line ] - @top_line, DONT_PITCH_CURSOR, DO_DISPLAY )
|
1159
|
-
cursorTo( cursor_state[ :row ], cursor_state[ :col ] )
|
1160
|
-
@diakonos.updateStatusLine
|
1161
|
-
end
|
1162
|
-
end
|
1163
|
-
|
1164
|
-
[ return_pointer, @cursor_stack.size ]
|
1165
|
-
end
|
1166
|
-
|
1167
|
-
def tabExpandedColumn( col, row )
|
1168
|
-
delta = 0
|
1169
|
-
line = @lines[ row ]
|
1170
|
-
for i in 0...col
|
1171
|
-
if line[ i ] == TAB
|
1172
|
-
delta += ( @tab_size - ( (i+delta) % @tab_size ) ) - 1
|
1173
|
-
end
|
1174
|
-
end
|
1175
|
-
col + delta
|
1176
|
-
end
|
1177
|
-
|
1178
|
-
def cursorToEOF
|
1179
|
-
cursorTo( @lines.length - 1, @lines[ -1 ].length, DO_DISPLAY )
|
1180
|
-
end
|
1181
|
-
|
1182
|
-
def cursorToBOL
|
1183
|
-
row = @last_row
|
1184
|
-
case @settings[ "bol_behaviour" ]
|
1185
|
-
when BOL_ZERO
|
1186
|
-
col = 0
|
1187
|
-
when BOL_FIRST_CHAR
|
1188
|
-
col = ( ( @lines[ row ] =~ /\S/ ) or 0 )
|
1189
|
-
when BOL_ALT_ZERO
|
1190
|
-
if @last_col == 0
|
1191
|
-
col = ( @lines[ row ] =~ /\S/ )
|
1192
|
-
else
|
1193
|
-
col = 0
|
1194
|
-
end
|
1195
|
-
#when BOL_ALT_FIRST_CHAR
|
1196
|
-
else
|
1197
|
-
first_char_col = ( ( @lines[ row ] =~ /\S/ ) or 0 )
|
1198
|
-
if @last_col == first_char_col
|
1199
|
-
col = 0
|
1200
|
-
else
|
1201
|
-
col = first_char_col
|
1202
|
-
end
|
1203
|
-
end
|
1204
|
-
cursorTo( row, col, DO_DISPLAY )
|
1205
|
-
end
|
1206
|
-
|
1207
|
-
def cursorToEOL
|
1208
|
-
y = @win_main.cury
|
1209
|
-
end_col = lineAt( y ).length
|
1210
|
-
last_char_col = lineAt( y ).rstrip.length
|
1211
|
-
case @settings[ 'eol_behaviour' ]
|
1212
|
-
when EOL_END
|
1213
|
-
col = end_col
|
1214
|
-
when EOL_LAST_CHAR
|
1215
|
-
col = last_char_col
|
1216
|
-
when EOL_ALT_LAST_CHAR
|
1217
|
-
if @last_col == last_char_col
|
1218
|
-
col = end_col
|
1219
|
-
else
|
1220
|
-
col = last_char_col
|
1221
|
-
end
|
1222
|
-
else
|
1223
|
-
if @last_col == end_col
|
1224
|
-
col = last_char_col
|
1225
|
-
else
|
1226
|
-
col = end_col
|
1227
|
-
end
|
1228
|
-
end
|
1229
|
-
cursorTo( @last_row, col, DO_DISPLAY )
|
1230
|
-
end
|
1231
|
-
|
1232
|
-
# Top of view
|
1233
|
-
def cursorToTOV
|
1234
|
-
cursorTo( rowOf( 0 ), @last_col, DO_DISPLAY )
|
1235
|
-
end
|
1236
|
-
# Bottom of view
|
1237
|
-
def cursorToBOV
|
1238
|
-
cursorTo( rowOf( 0 + @diakonos.main_window_height - 1 ), @last_col, DO_DISPLAY )
|
1239
|
-
end
|
1240
|
-
|
1241
|
-
# col and row are given relative to the buffer, not any window or screen.
|
1242
|
-
# Returns true if the view changed positions.
|
1243
|
-
def showCharacter( row, col )
|
1244
|
-
old_top_line = @top_line
|
1245
|
-
old_left_column = @left_column
|
1246
|
-
|
1247
|
-
while row < @top_line + @settings[ "view.margin.y" ]
|
1248
|
-
amount = (-1) * @settings[ "view.jump.y" ]
|
1249
|
-
break if( pitchView( amount, DONT_PITCH_CURSOR, DONT_DISPLAY ) != amount )
|
1250
|
-
end
|
1251
|
-
while row > @top_line + @diakonos.main_window_height - 1 - @settings[ "view.margin.y" ]
|
1252
|
-
amount = @settings[ "view.jump.y" ]
|
1253
|
-
break if( pitchView( amount, DONT_PITCH_CURSOR, DONT_DISPLAY ) != amount )
|
1254
|
-
end
|
1255
|
-
|
1256
|
-
while col < @left_column + @settings[ "view.margin.x" ]
|
1257
|
-
amount = (-1) * @settings[ "view.jump.x" ]
|
1258
|
-
break if( panView( amount, DONT_DISPLAY ) != amount )
|
1259
|
-
end
|
1260
|
-
while col > @left_column + @diakonos.main_window_width - @settings[ "view.margin.x" ] - 2
|
1261
|
-
amount = @settings[ "view.jump.x" ]
|
1262
|
-
break if( panView( amount, DONT_DISPLAY ) != amount )
|
1263
|
-
end
|
1264
|
-
|
1265
|
-
@top_line != old_top_line or @left_column != old_left_column
|
1266
|
-
end
|
1267
|
-
|
1268
|
-
def setIndent( row, level, do_display = DO_DISPLAY )
|
1269
|
-
@lines[ row ] =~ /^([\s#{@indent_ignore_charset}]*)(.*)$/
|
1270
|
-
current_indent_text = ( $1 or "" )
|
1271
|
-
rest = ( $2 or "" )
|
1272
|
-
current_indent_text.gsub!( /\t/, ' ' * @tab_size )
|
1273
|
-
indentation = @indent_size * [ level, 0 ].max
|
1274
|
-
if current_indent_text.length >= indentation
|
1275
|
-
indent_text = current_indent_text[ 0...indentation ]
|
1276
|
-
else
|
1277
|
-
indent_text = current_indent_text + " " * ( indentation - current_indent_text.length )
|
1278
|
-
end
|
1279
|
-
if @settings[ "lang.#{@language}.indent.using_tabs" ]
|
1280
|
-
num_tabs = 0
|
1281
|
-
indent_text.gsub!( / {#{@tab_size}}/ ) { |match|
|
1282
|
-
num_tabs += 1
|
1283
|
-
"\t"
|
1284
|
-
}
|
1285
|
-
indentation -= num_tabs * ( @tab_size - 1 )
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
takeSnapshot( TYPING ) if do_display
|
1289
|
-
@lines[ row ] = indent_text + rest
|
1290
|
-
cursorTo( row, indentation ) if do_display
|
1291
|
-
setModified
|
1292
|
-
end
|
1293
|
-
|
1294
|
-
def parsedIndent( row = @last_row, do_display = DO_DISPLAY )
|
1295
|
-
if row == 0
|
1296
|
-
level = 0
|
1297
|
-
else
|
1298
|
-
# Look upwards for the nearest line on which to base this line's indentation.
|
1299
|
-
i = 1
|
1300
|
-
while ( @lines[ row - i ] =~ /^[\s#{@indent_ignore_charset}]*$/ ) or
|
1301
|
-
( @lines[ row - i ] =~ @settings[ "lang.#{@language}.indent.ignore" ] )
|
1302
|
-
i += 1
|
1303
|
-
end
|
1304
|
-
if row - i < 0
|
1305
|
-
level = 0
|
1306
|
-
else
|
1307
|
-
prev_line = @lines[ row - i ]
|
1308
|
-
level = prev_line.indentation_level( @indent_size, @indent_roundup, @tab_size, @indent_ignore_charset )
|
1309
|
-
|
1310
|
-
line = @lines[ row ]
|
1311
|
-
if @preventers
|
1312
|
-
prev_line = prev_line.gsub( @preventers, "" )
|
1313
|
-
line = line.gsub( @preventers, "" )
|
1314
|
-
end
|
1315
|
-
|
1316
|
-
indenter_index = ( prev_line =~ @indenters )
|
1317
|
-
if indenter_index
|
1318
|
-
level += 1
|
1319
|
-
unindenter_index = (prev_line =~ @unindenters)
|
1320
|
-
if unindenter_index and unindenter_index != indenter_index
|
1321
|
-
level += -1
|
1322
|
-
end
|
1323
|
-
end
|
1324
|
-
if line =~ @unindenters
|
1325
|
-
level += -1
|
1326
|
-
end
|
1327
|
-
end
|
1328
|
-
end
|
1329
|
-
|
1330
|
-
setIndent( row, level, do_display )
|
1331
|
-
|
1332
|
-
end
|
1333
|
-
|
1334
|
-
def indent( row = @last_row, do_display = DO_DISPLAY )
|
1335
|
-
level = @lines[ row ].indentation_level( @indent_size, @indent_roundup, @tab_size )
|
1336
|
-
setIndent( row, level + 1, do_display )
|
1337
|
-
end
|
1338
|
-
|
1339
|
-
def unindent( row = @last_row, do_display = DO_DISPLAY )
|
1340
|
-
level = @lines[ row ].indentation_level( @indent_size, @indent_roundup, @tab_size )
|
1341
|
-
setIndent( row, level - 1, do_display )
|
1342
|
-
end
|
1343
|
-
|
1344
|
-
def anchorSelection( row = @last_row, col = @last_col, do_display = DO_DISPLAY )
|
1345
|
-
@mark_anchor = ( @mark_anchor or Hash.new )
|
1346
|
-
@mark_anchor[ "row" ] = row
|
1347
|
-
@mark_anchor[ "col" ] = col
|
1348
|
-
recordMarkStartAndEnd
|
1349
|
-
@changing_selection = true
|
1350
|
-
display if do_display
|
1351
|
-
end
|
1352
|
-
|
1353
|
-
def removeSelection( do_display = DO_DISPLAY )
|
1354
|
-
return if selection_mark.nil?
|
1355
|
-
@mark_anchor = nil
|
1356
|
-
recordMarkStartAndEnd
|
1357
|
-
@changing_selection = false
|
1358
|
-
@last_finding = nil
|
1359
|
-
display if do_display
|
1360
|
-
end
|
1361
|
-
|
1362
|
-
def toggleSelection
|
1363
|
-
if @changing_selection
|
1364
|
-
removeSelection
|
1365
|
-
else
|
1366
|
-
anchorSelection
|
1367
|
-
end
|
1368
|
-
end
|
1369
|
-
|
1370
|
-
def copySelection
|
1371
|
-
selected_text
|
1372
|
-
end
|
1373
|
-
def selected_text
|
1374
|
-
selection = selection_mark
|
1375
|
-
if selection.nil?
|
1376
|
-
nil
|
1377
|
-
elsif selection.start_row == selection.end_row
|
1378
|
-
[ @lines[ selection.start_row ][ selection.start_col...selection.end_col ] ]
|
1379
|
-
else
|
1380
|
-
[ @lines[ selection.start_row ][ selection.start_col..-1 ] ] +
|
1381
|
-
( @lines[ (selection.start_row + 1) .. (selection.end_row - 1) ] or [] ) +
|
1382
|
-
[ @lines[ selection.end_row ][ 0...selection.end_col ] ]
|
1383
|
-
end
|
1384
|
-
end
|
1385
|
-
def selected_string
|
1386
|
-
lines = selected_text
|
1387
|
-
if lines
|
1388
|
-
lines.join( "\n" )
|
1389
|
-
else
|
1390
|
-
nil
|
1391
|
-
end
|
1392
|
-
end
|
1393
|
-
|
1394
|
-
def deleteSelection( do_display = DO_DISPLAY )
|
1395
|
-
return if @text_marks[ SELECTION ].nil?
|
1396
|
-
|
1397
|
-
takeSnapshot
|
1398
|
-
|
1399
|
-
selection = @text_marks[ SELECTION ]
|
1400
|
-
start_row = selection.start_row
|
1401
|
-
start_col = selection.start_col
|
1402
|
-
start_line = @lines[ start_row ]
|
1403
|
-
|
1404
|
-
if selection.end_row == selection.start_row
|
1405
|
-
@lines[ start_row ] = start_line[ 0...start_col ] + start_line[ selection.end_col..-1 ]
|
1406
|
-
else
|
1407
|
-
end_line = @lines[ selection.end_row ]
|
1408
|
-
@lines[ start_row ] = start_line[ 0...start_col ] + end_line[ selection.end_col..-1 ]
|
1409
|
-
@lines = @lines[ 0..start_row ] + @lines[ (selection.end_row + 1)..-1 ]
|
1410
|
-
end
|
1411
|
-
|
1412
|
-
cursorTo( start_row, start_col )
|
1413
|
-
removeSelection( DONT_DISPLAY )
|
1414
|
-
setModified( do_display )
|
1415
|
-
end
|
1416
|
-
|
1417
|
-
# text is an array of Strings, or a String with zero or more newlines ("\n")
|
1418
|
-
def paste( text, do_parsed_indent = false )
|
1419
|
-
return if text.nil?
|
1420
|
-
|
1421
|
-
if not text.kind_of? Array
|
1422
|
-
s = text.to_s
|
1423
|
-
if s.include?( "\n" )
|
1424
|
-
text = s.split( "\n", -1 )
|
1425
|
-
else
|
1426
|
-
text = [ s ]
|
1427
|
-
end
|
1428
|
-
end
|
1429
|
-
|
1430
|
-
takeSnapshot
|
1431
|
-
|
1432
|
-
deleteSelection( DONT_DISPLAY )
|
1433
|
-
|
1434
|
-
row = @last_row
|
1435
|
-
col = @last_col
|
1436
|
-
line = @lines[ row ]
|
1437
|
-
if text.length == 1
|
1438
|
-
@lines[ row ] = line[ 0...col ] + text[ 0 ] + line[ col..-1 ]
|
1439
|
-
if do_parsed_indent
|
1440
|
-
parsedIndent row, DONT_DISPLAY
|
1441
|
-
end
|
1442
|
-
cursorTo( @last_row, @last_col + text[ 0 ].length )
|
1443
|
-
elsif text.length > 1
|
1444
|
-
@lines[ row ] = line[ 0...col ] + text[ 0 ]
|
1445
|
-
@lines[ row + 1, 0 ] = text[ -1 ] + line[ col..-1 ]
|
1446
|
-
@lines[ row + 1, 0 ] = text[ 1..-2 ]
|
1447
|
-
new_row = @last_row + text.length - 1
|
1448
|
-
if do_parsed_indent
|
1449
|
-
( row..new_row ).each do |r|
|
1450
|
-
parsedIndent r, DONT_DISPLAY
|
1451
|
-
end
|
1452
|
-
end
|
1453
|
-
cursorTo( new_row, columnOf( text[ -1 ].length ) )
|
1454
|
-
end
|
1455
|
-
|
1456
|
-
setModified
|
1457
|
-
end
|
1458
|
-
|
1459
|
-
# Takes an array of Regexps, which represents a user-provided regexp,
|
1460
|
-
# split across newline characters. Once the first element is found,
|
1461
|
-
# each successive element must match against lines following the first
|
1462
|
-
# element.
|
1463
|
-
def find( regexps, options = {} )
|
1464
|
-
return if regexps.nil?
|
1465
|
-
regexp = regexps[ 0 ]
|
1466
|
-
return if regexp.nil? or regexp == //
|
1467
|
-
|
1468
|
-
direction = options[ :direction ]
|
1469
|
-
replacement = options[ :replacement ]
|
1470
|
-
auto_choice = options[ :auto_choice ]
|
1471
|
-
from_row = options[ :starting_row ] || @last_row
|
1472
|
-
from_col = options[ :starting_col ] || @last_col
|
1473
|
-
|
1474
|
-
if direction == :opposite
|
1475
|
-
case @last_search_direction
|
1476
|
-
when :up
|
1477
|
-
direction = :down
|
1478
|
-
else
|
1479
|
-
direction = :up
|
1480
|
-
end
|
1481
|
-
end
|
1482
|
-
@last_search_regexps = regexps
|
1483
|
-
@last_search_direction = direction
|
1484
|
-
|
1485
|
-
finding = nil
|
1486
|
-
wrapped = false
|
1487
|
-
match = nil
|
1488
|
-
|
1489
|
-
catch :found do
|
1490
|
-
|
1491
|
-
if direction == :down
|
1492
|
-
# Check the current row first.
|
1493
|
-
|
1494
|
-
if index = @lines[ from_row ].index( regexp, ( @last_finding ? @last_finding.start_col : from_col ) + 1 )
|
1495
|
-
match = Regexp.last_match
|
1496
|
-
found_text = match[ 0 ]
|
1497
|
-
finding = Finding.new( from_row, index, from_row, index + found_text.length )
|
1498
|
-
if finding.match( regexps, @lines )
|
1499
|
-
throw :found
|
1500
|
-
else
|
1501
|
-
finding = nil
|
1502
|
-
end
|
1503
|
-
end
|
1504
|
-
|
1505
|
-
# Check below the cursor.
|
1506
|
-
|
1507
|
-
( (from_row + 1)...@lines.length ).each do |i|
|
1508
|
-
if index = @lines[ i ].index( regexp )
|
1509
|
-
match = Regexp.last_match
|
1510
|
-
found_text = match[ 0 ]
|
1511
|
-
finding = Finding.new( i, index, i, index + found_text.length )
|
1512
|
-
if finding.match( regexps, @lines )
|
1513
|
-
throw :found
|
1514
|
-
else
|
1515
|
-
finding = nil
|
1516
|
-
end
|
1517
|
-
end
|
1518
|
-
end
|
1519
|
-
|
1520
|
-
# Wrap around.
|
1521
|
-
|
1522
|
-
wrapped = true
|
1523
|
-
|
1524
|
-
( 0...from_row ).each do |i|
|
1525
|
-
if index = @lines[ i ].index( regexp )
|
1526
|
-
match = Regexp.last_match
|
1527
|
-
found_text = match[ 0 ]
|
1528
|
-
finding = Finding.new( i, index, i, index + found_text.length )
|
1529
|
-
if finding.match( regexps, @lines )
|
1530
|
-
throw :found
|
1531
|
-
else
|
1532
|
-
finding = nil
|
1533
|
-
end
|
1534
|
-
end
|
1535
|
-
end
|
1536
|
-
|
1537
|
-
# And finally, the other side of the current row.
|
1538
|
-
|
1539
|
-
#if index = @lines[ from_row ].index( regexp, ( @last_finding ? @last_finding.start_col : from_col ) - 1 )
|
1540
|
-
if index = @lines[ from_row ].index( regexp )
|
1541
|
-
if index <= ( @last_finding ? @last_finding.start_col : from_col )
|
1542
|
-
match = Regexp.last_match
|
1543
|
-
found_text = match[ 0 ]
|
1544
|
-
finding = Finding.new( from_row, index, from_row, index + found_text.length )
|
1545
|
-
if finding.match( regexps, @lines )
|
1546
|
-
throw :found
|
1547
|
-
else
|
1548
|
-
finding = nil
|
1549
|
-
end
|
1550
|
-
end
|
1551
|
-
end
|
1552
|
-
|
1553
|
-
elsif direction == :up
|
1554
|
-
# Check the current row first.
|
1555
|
-
|
1556
|
-
col_to_check = ( @last_finding ? @last_finding.end_col : from_col ) - 1
|
1557
|
-
if ( col_to_check >= 0 ) and ( index = @lines[ from_row ][ 0...col_to_check ].rindex( regexp ) )
|
1558
|
-
match = Regexp.last_match
|
1559
|
-
found_text = match[ 0 ]
|
1560
|
-
finding = Finding.new( from_row, index, from_row, index + found_text.length )
|
1561
|
-
if finding.match( regexps, @lines )
|
1562
|
-
throw :found
|
1563
|
-
else
|
1564
|
-
finding = nil
|
1565
|
-
end
|
1566
|
-
end
|
1567
|
-
|
1568
|
-
# Check above the cursor.
|
1569
|
-
|
1570
|
-
(from_row - 1).downto( 0 ) do |i|
|
1571
|
-
if index = @lines[ i ].rindex( regexp )
|
1572
|
-
match = Regexp.last_match
|
1573
|
-
found_text = match[ 0 ]
|
1574
|
-
finding = Finding.new( i, index, i, index + found_text.length )
|
1575
|
-
if finding.match( regexps, @lines )
|
1576
|
-
throw :found
|
1577
|
-
else
|
1578
|
-
finding = nil
|
1579
|
-
end
|
1580
|
-
end
|
1581
|
-
end
|
1582
|
-
|
1583
|
-
# Wrap around.
|
1584
|
-
|
1585
|
-
wrapped = true
|
1586
|
-
|
1587
|
-
(@lines.length - 1).downto(from_row + 1) do |i|
|
1588
|
-
if index = @lines[ i ].rindex( regexp )
|
1589
|
-
match = Regexp.last_match
|
1590
|
-
found_text = match[ 0 ]
|
1591
|
-
finding = Finding.new( i, index, i, index + found_text.length )
|
1592
|
-
if finding.match( regexps, @lines )
|
1593
|
-
throw :found
|
1594
|
-
else
|
1595
|
-
finding = nil
|
1596
|
-
end
|
1597
|
-
end
|
1598
|
-
end
|
1599
|
-
|
1600
|
-
# And finally, the other side of the current row.
|
1601
|
-
|
1602
|
-
search_col = ( @last_finding ? @last_finding.start_col : from_col ) + 1
|
1603
|
-
if index = @lines[ from_row ].rindex( regexp )
|
1604
|
-
if index > search_col
|
1605
|
-
match = Regexp.last_match
|
1606
|
-
found_text = match[ 0 ]
|
1607
|
-
finding = Finding.new( from_row, index, from_row, index + found_text.length )
|
1608
|
-
if finding.match( regexps, @lines )
|
1609
|
-
throw :found
|
1610
|
-
else
|
1611
|
-
finding = nil
|
1612
|
-
end
|
1613
|
-
end
|
1614
|
-
end
|
1615
|
-
end
|
1616
|
-
end
|
1617
|
-
|
1618
|
-
if finding
|
1619
|
-
if wrapped and not options[ :quiet ]
|
1620
|
-
@diakonos.setILine( "(search wrapped around BOF/EOF)" )
|
1621
|
-
end
|
1622
|
-
|
1623
|
-
removeSelection( DONT_DISPLAY )
|
1624
|
-
@last_finding = finding
|
1625
|
-
if @settings[ "found_cursor_start" ]
|
1626
|
-
anchorSelection( finding.end_row, finding.end_col, DONT_DISPLAY )
|
1627
|
-
cursorTo( finding.start_row, finding.start_col )
|
1628
|
-
else
|
1629
|
-
anchorSelection( finding.start_row, finding.start_col, DONT_DISPLAY )
|
1630
|
-
cursorTo( finding.end_row, finding.end_col )
|
1631
|
-
end
|
1632
|
-
|
1633
|
-
@changing_selection = false
|
1634
|
-
|
1635
|
-
if regexps.length == 1
|
1636
|
-
@highlight_regexp = regexp
|
1637
|
-
highlightMatches
|
1638
|
-
else
|
1639
|
-
clearMatches
|
1640
|
-
end
|
1641
|
-
display
|
1642
|
-
|
1643
|
-
if replacement
|
1644
|
-
# Substitute placeholders (e.g. \1) in str for the group matches of the last match.
|
1645
|
-
actual_replacement = replacement.dup
|
1646
|
-
actual_replacement.gsub!( /\\(\\|\d+)/ ) { |m|
|
1647
|
-
ref = $1
|
1648
|
-
if ref == "\\"
|
1649
|
-
"\\"
|
1650
|
-
else
|
1651
|
-
match[ ref.to_i ]
|
1652
|
-
end
|
1653
|
-
}
|
1654
|
-
|
1655
|
-
choice = auto_choice || @diakonos.getChoice(
|
1656
|
-
"Replace?",
|
1657
|
-
[ CHOICE_YES, CHOICE_NO, CHOICE_ALL, CHOICE_CANCEL, CHOICE_YES_AND_STOP ],
|
1658
|
-
CHOICE_YES
|
1659
|
-
)
|
1660
|
-
case choice
|
1661
|
-
when CHOICE_YES
|
1662
|
-
paste [ actual_replacement ]
|
1663
|
-
find( regexps, :direction => direction, :replacement => replacement )
|
1664
|
-
when CHOICE_ALL
|
1665
|
-
replaceAll( regexp, replacement )
|
1666
|
-
when CHOICE_NO
|
1667
|
-
find( regexps, :direction => direction, :replacement => replacement )
|
1668
|
-
when CHOICE_CANCEL
|
1669
|
-
# Do nothing further.
|
1670
|
-
when CHOICE_YES_AND_STOP
|
1671
|
-
paste [ actual_replacement ]
|
1672
|
-
# Do nothing further.
|
1673
|
-
end
|
1674
|
-
end
|
1675
|
-
else
|
1676
|
-
removeSelection DONT_DISPLAY
|
1677
|
-
clearMatches DO_DISPLAY
|
1678
|
-
if not options[ :quiet ]
|
1679
|
-
@diakonos.setILine "/#{regexp.source}/ not found."
|
1680
|
-
end
|
1681
|
-
end
|
1682
|
-
end
|
1683
|
-
|
1684
|
-
def replaceAll( regexp, replacement )
|
1685
|
-
return if( regexp.nil? or replacement.nil? )
|
1686
|
-
|
1687
|
-
@lines = @lines.collect { |line|
|
1688
|
-
line.gsub( regexp, replacement )
|
1689
|
-
}
|
1690
|
-
setModified
|
1691
|
-
|
1692
|
-
clearMatches
|
1693
|
-
|
1694
|
-
display
|
1695
|
-
end
|
1696
|
-
|
1697
|
-
def highlightMatches( regexp = @highlight_regexp )
|
1698
|
-
@highlight_regexp = regexp
|
1699
|
-
return if @highlight_regexp.nil?
|
1700
|
-
found_marks = @lines[ @top_line...(@top_line + @diakonos.main_window_height) ].grep_indices( @highlight_regexp ).collect do |line_index, start_col, end_col|
|
1701
|
-
TextMark.new( @top_line + line_index, start_col, @top_line + line_index, end_col, @settings[ "lang.#{@language}.format.found" ] )
|
1702
|
-
end
|
1703
|
-
@text_marks = [ @text_marks[ 0 ] ] + found_marks
|
1704
|
-
end
|
1705
|
-
|
1706
|
-
def clearMatches( do_display = DONT_DISPLAY )
|
1707
|
-
selection = @text_marks[ SELECTION ]
|
1708
|
-
@text_marks = Array.new
|
1709
|
-
@text_marks[ SELECTION ] = selection
|
1710
|
-
@highlight_regexp = nil
|
1711
|
-
display if do_display
|
1712
|
-
end
|
1713
|
-
|
1714
|
-
def findAgain( last_search_regexps, direction = @last_search_direction )
|
1715
|
-
if @last_search_regexps.nil?
|
1716
|
-
@last_search_regexps = last_search_regexps
|
1717
|
-
end
|
1718
|
-
if @last_search_regexps
|
1719
|
-
find( @last_search_regexps, :direction => direction )
|
1720
|
-
end
|
1721
|
-
end
|
1722
|
-
|
1723
|
-
def seek( regexp, direction = :down )
|
1724
|
-
return if regexp.nil? or regexp == //
|
1725
|
-
|
1726
|
-
found_row = nil
|
1727
|
-
found_col = nil
|
1728
|
-
found_text = nil
|
1729
|
-
wrapped = false
|
1730
|
-
|
1731
|
-
catch :found do
|
1732
|
-
if direction == :down
|
1733
|
-
# Check the current row first.
|
1734
|
-
|
1735
|
-
index, match_text = @lines[ @last_row ].group_index( regexp, @last_col + 1 )
|
1736
|
-
if index
|
1737
|
-
found_row = @last_row
|
1738
|
-
found_col = index
|
1739
|
-
found_text = match_text
|
1740
|
-
throw :found
|
1741
|
-
end
|
1742
|
-
|
1743
|
-
# Check below the cursor.
|
1744
|
-
|
1745
|
-
( (@last_row + 1)...@lines.length ).each do |i|
|
1746
|
-
index, match_text = @lines[ i ].group_index( regexp )
|
1747
|
-
if index
|
1748
|
-
found_row = i
|
1749
|
-
found_col = index
|
1750
|
-
found_text = match_text
|
1751
|
-
throw :found
|
1752
|
-
end
|
1753
|
-
end
|
1754
|
-
|
1755
|
-
else
|
1756
|
-
# Check the current row first.
|
1757
|
-
|
1758
|
-
#col_to_check = ( @last_found_col or @last_col ) - 1
|
1759
|
-
col_to_check = @last_col - 1
|
1760
|
-
if col_to_check >= 0
|
1761
|
-
index, match_text = @lines[ @last_row ].group_rindex( regexp, col_to_check )
|
1762
|
-
if index
|
1763
|
-
found_row = @last_row
|
1764
|
-
found_col = index
|
1765
|
-
found_text = match_text
|
1766
|
-
throw :found
|
1767
|
-
end
|
1768
|
-
end
|
1769
|
-
|
1770
|
-
# Check above the cursor.
|
1771
|
-
|
1772
|
-
(@last_row - 1).downto( 0 ) do |i|
|
1773
|
-
index, match_text = @lines[ i ].group_rindex( regexp )
|
1774
|
-
if index
|
1775
|
-
found_row = i
|
1776
|
-
found_col = index
|
1777
|
-
found_text = match_text
|
1778
|
-
throw :found
|
1779
|
-
end
|
1780
|
-
end
|
1781
|
-
end
|
1782
|
-
end
|
1783
|
-
|
1784
|
-
if found_text
|
1785
|
-
#@last_found_row = found_row
|
1786
|
-
#@last_found_col = found_col
|
1787
|
-
cursorTo( found_row, found_col )
|
1788
|
-
|
1789
|
-
display
|
1790
|
-
end
|
1791
|
-
end
|
1792
|
-
|
1793
|
-
# Returns an Array of results, where each result is a String usually
|
1794
|
-
# containing \n's due to context
|
1795
|
-
def grep( regexp_source )
|
1796
|
-
::Diakonos.grep_array(
|
1797
|
-
Regexp.new( regexp_source ),
|
1798
|
-
@lines,
|
1799
|
-
@diakonos.settings[ 'grep.context' ],
|
1800
|
-
"#{File.basename( @name )}:",
|
1801
|
-
@key
|
1802
|
-
)
|
1803
|
-
end
|
1804
|
-
|
1805
|
-
def setModified( do_display = DO_DISPLAY )
|
1806
|
-
if @read_only
|
1807
|
-
@diakonos.setILine "Warning: Modifying a read-only file."
|
1808
|
-
end
|
1809
|
-
|
1810
|
-
fmod = false
|
1811
|
-
if not @modified
|
1812
|
-
@modified = true
|
1813
|
-
fmod = file_modified?
|
1814
|
-
end
|
1815
|
-
|
1816
|
-
reverted = false
|
1817
|
-
if fmod
|
1818
|
-
reverted = @diakonos.revert( "File has been altered externally. Load on-disk version?" )
|
1819
|
-
end
|
1820
|
-
|
1821
|
-
if not reverted
|
1822
|
-
clearMatches
|
1823
|
-
if do_display
|
1824
|
-
@diakonos.updateStatusLine
|
1825
|
-
display
|
1826
|
-
end
|
1827
|
-
end
|
1828
|
-
end
|
1829
|
-
|
1830
|
-
# Check if the file which is being edited has been modified since
|
1831
|
-
# the last time we checked it; return true if so, false otherwise.
|
1832
|
-
def file_modified?
|
1833
|
-
modified = false
|
1834
|
-
|
1835
|
-
if @name
|
1836
|
-
begin
|
1837
|
-
mtime = File.mtime( @name )
|
1838
|
-
|
1839
|
-
if mtime > @last_modification_check
|
1840
|
-
modified = true
|
1841
|
-
@last_modification_check = mtime
|
1842
|
-
end
|
1843
|
-
rescue Errno::ENOENT
|
1844
|
-
# Ignore if file doesn't exist
|
1845
|
-
end
|
1846
|
-
end
|
1847
|
-
|
1848
|
-
modified
|
1849
|
-
end
|
1850
|
-
|
1851
|
-
# Compares MD5 sums of buffer and actual file on disk.
|
1852
|
-
# Returns true if there is no file on disk.
|
1853
|
-
def file_different?
|
1854
|
-
if @name
|
1855
|
-
Digest::MD5.hexdigest(
|
1856
|
-
@lines.join( "\n" )
|
1857
|
-
) != Digest::MD5.hexdigest(
|
1858
|
-
File.read( @name )
|
1859
|
-
)
|
1860
|
-
else
|
1861
|
-
true
|
1862
|
-
end
|
1863
|
-
end
|
1864
|
-
|
1865
|
-
def takeSnapshot( typing = false )
|
1866
|
-
take_snapshot = false
|
1867
|
-
if @typing != typing
|
1868
|
-
@typing = typing
|
1869
|
-
# If we just started typing, take a snapshot, but don't continue
|
1870
|
-
# taking snapshots for every keystroke
|
1871
|
-
if typing
|
1872
|
-
take_snapshot = true
|
1873
|
-
end
|
1874
|
-
end
|
1875
|
-
if not @typing
|
1876
|
-
take_snapshot = true
|
1877
|
-
end
|
1878
|
-
|
1879
|
-
if take_snapshot
|
1880
|
-
undo_size = 0
|
1881
|
-
@buffer_states[ 1..-1 ].each do |state|
|
1882
|
-
undo_size += state.length
|
1883
|
-
end
|
1884
|
-
while ( ( undo_size + @lines.length ) >= @settings[ "max_undo_lines" ] ) and @buffer_states.length > 1
|
1885
|
-
@cursor_states.pop
|
1886
|
-
popped_state = @buffer_states.pop
|
1887
|
-
undo_size = undo_size - popped_state.length
|
1888
|
-
end
|
1889
|
-
if @current_buffer_state > 0
|
1890
|
-
@buffer_states.unshift @lines.deep_clone
|
1891
|
-
@cursor_states.unshift [ @last_row, @last_col ]
|
1892
|
-
end
|
1893
|
-
@buffer_states.unshift @lines.deep_clone
|
1894
|
-
@cursor_states.unshift [ @last_row, @last_col ]
|
1895
|
-
@current_buffer_state = 0
|
1896
|
-
@lines = @buffer_states[ @current_buffer_state ]
|
1897
|
-
end
|
1898
|
-
end
|
1899
|
-
|
1900
|
-
def undo
|
1901
|
-
if @current_buffer_state < @buffer_states.length - 1
|
1902
|
-
@current_buffer_state += 1
|
1903
|
-
@lines = @buffer_states[ @current_buffer_state ]
|
1904
|
-
cursorTo( @cursor_states[ @current_buffer_state - 1 ][ 0 ], @cursor_states[ @current_buffer_state - 1 ][ 1 ] )
|
1905
|
-
@diakonos.setILine "Undo level: #{@current_buffer_state} of #{@buffer_states.length - 1}"
|
1906
|
-
setModified
|
1907
|
-
end
|
1908
|
-
end
|
1909
|
-
|
1910
|
-
# Since redo is a Ruby keyword...
|
1911
|
-
def unundo
|
1912
|
-
if @current_buffer_state > 0
|
1913
|
-
@current_buffer_state += -1
|
1914
|
-
@lines = @buffer_states[ @current_buffer_state ]
|
1915
|
-
cursorTo( @cursor_states[ @current_buffer_state ][ 0 ], @cursor_states[ @current_buffer_state ][ 1 ] )
|
1916
|
-
@diakonos.setILine "Undo level: #{@current_buffer_state} of #{@buffer_states.length - 1}"
|
1917
|
-
setModified
|
1918
|
-
end
|
1919
|
-
end
|
1920
|
-
|
1921
|
-
def wrap_paragraph
|
1922
|
-
start_row = end_row = @last_row
|
1923
|
-
until start_row == 0 || @lines[ start_row - 1 ].strip == ''
|
1924
|
-
start_row -= 1
|
1925
|
-
end
|
1926
|
-
until end_row == @lines.size || @lines[ end_row ].strip == ''
|
1927
|
-
end_row += 1
|
1928
|
-
end
|
1929
|
-
|
1930
|
-
lines = []
|
1931
|
-
line = ''
|
1932
|
-
words = @lines[ start_row...end_row ].join( ' ' ).scan( /\S+/ )
|
1933
|
-
words.each do |word|
|
1934
|
-
if word =~ /^[a-z']+[.!?]$/
|
1935
|
-
word = "#{word} "
|
1936
|
-
end
|
1937
|
-
if line.length + word.length + 1 > ( @settings[ "lang.#{@language}.wrap_margin" ] || 80 )
|
1938
|
-
lines << line.strip
|
1939
|
-
line = ''
|
1940
|
-
end
|
1941
|
-
line << " #{word}"
|
1942
|
-
end
|
1943
|
-
line.strip!
|
1944
|
-
if not line.empty?
|
1945
|
-
lines << line
|
1946
|
-
end
|
1947
|
-
if @lines[ start_row...end_row ] != lines
|
1948
|
-
@lines[ start_row...end_row ] = lines
|
1949
|
-
setModified
|
1950
|
-
end
|
1951
|
-
end
|
1952
|
-
|
1953
|
-
def goToLine( line = nil, column = nil )
|
1954
|
-
cursorTo( line || @last_row, column || 0, DO_DISPLAY )
|
1955
|
-
end
|
1956
|
-
|
1957
|
-
def goToNextBookmark
|
1958
|
-
cur_pos = Bookmark.new( self, @last_row, @last_col )
|
1959
|
-
next_bm = @bookmarks.find do |bm|
|
1960
|
-
bm > cur_pos
|
1961
|
-
end
|
1962
|
-
if next_bm
|
1963
|
-
cursorTo( next_bm.row, next_bm.col, DO_DISPLAY )
|
1964
|
-
end
|
1965
|
-
end
|
1966
|
-
|
1967
|
-
def goToPreviousBookmark
|
1968
|
-
cur_pos = Bookmark.new( self, @last_row, @last_col )
|
1969
|
-
# There's no reverse_find method, so, we have to do this manually.
|
1970
|
-
prev = nil
|
1971
|
-
@bookmarks.reverse_each do |bm|
|
1972
|
-
if bm < cur_pos
|
1973
|
-
prev = bm
|
1974
|
-
break
|
1975
|
-
end
|
1976
|
-
end
|
1977
|
-
if prev
|
1978
|
-
cursorTo( prev.row, prev.col, DO_DISPLAY )
|
1979
|
-
end
|
1980
|
-
end
|
1981
|
-
|
1982
|
-
def toggleBookmark
|
1983
|
-
bookmark = Bookmark.new( self, @last_row, @last_col )
|
1984
|
-
existing = @bookmarks.find do |bm|
|
1985
|
-
bm == bookmark
|
1986
|
-
end
|
1987
|
-
if existing
|
1988
|
-
@bookmarks.delete existing
|
1989
|
-
@diakonos.setILine "Bookmark #{existing.to_s} deleted."
|
1990
|
-
else
|
1991
|
-
@bookmarks.push bookmark
|
1992
|
-
@bookmarks.sort
|
1993
|
-
@diakonos.setILine "Bookmark #{bookmark.to_s} set."
|
1994
|
-
end
|
1995
|
-
end
|
1996
|
-
|
1997
|
-
def context
|
1998
|
-
retval = Array.new
|
1999
|
-
row = @last_row
|
2000
|
-
clevel = @lines[ row ].indentation_level( @indent_size, @indent_roundup, @tab_size, @indent_ignore_charset )
|
2001
|
-
while row > 0 and clevel < 0
|
2002
|
-
row = row - 1
|
2003
|
-
clevel = @lines[ row ].indentation_level( @indent_size, @indent_roundup, @tab_size, @indent_ignore_charset )
|
2004
|
-
end
|
2005
|
-
clevel = 0 if clevel < 0
|
2006
|
-
while row > 0
|
2007
|
-
row = row - 1
|
2008
|
-
line = @lines[ row ]
|
2009
|
-
if line !~ @settings[ "lang.#{@language}.context.ignore" ]
|
2010
|
-
level = line.indentation_level( @indent_size, @indent_roundup, @tab_size, @indent_ignore_charset )
|
2011
|
-
if level < clevel and level > -1
|
2012
|
-
retval.unshift line
|
2013
|
-
clevel = level
|
2014
|
-
break if clevel == 0
|
2015
|
-
end
|
2016
|
-
end
|
2017
|
-
end
|
2018
|
-
retval
|
2019
|
-
end
|
2020
|
-
|
2021
|
-
def setType( type )
|
2022
|
-
if type
|
2023
|
-
configure( type )
|
2024
|
-
display
|
2025
|
-
true
|
2026
|
-
end
|
2027
|
-
end
|
2028
|
-
|
2029
|
-
def wordUnderCursor
|
2030
|
-
word = nil
|
2031
|
-
|
2032
|
-
@lines[ @last_row ].scan( /\w+/ ) do |match_text|
|
2033
|
-
last_match = Regexp.last_match
|
2034
|
-
if last_match.begin( 0 ) <= @last_col and @last_col < last_match.end( 0 )
|
2035
|
-
word = match_text
|
2036
|
-
break
|
2037
|
-
end
|
2038
|
-
end
|
2039
|
-
|
2040
|
-
word
|
2041
|
-
end
|
2042
|
-
end
|
2043
|
-
|
2044
|
-
end
|