Class: Ruvi::DocumentBuffer

Inherits:
Object
  • Object
show all
Extended by:
AccessorProxier
Defined in:
lib/buffer.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from AccessorProxier

proxy_accessors_to_object

Constructor Details

#initialize(app, lines = BufferLineArray.new, data = nil) ⇒ DocumentBuffer

Returns a new instance of DocumentBuffer.



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/buffer.rb', line 170

def initialize app, lines = BufferLineArray.new, data = nil
    if data.nil?
    @data = BufferData.new
    @data.highlight_cache = []
    @data.needs_redraw = false
    end
    @got_a_scroll_already = false
    @need_to_scroll = 0
    if data.nil?
    @data.redraw_list = []
    @data.app = app
    @data.lines = lines
    @data.fname = nil
    end
    @top   = 0
    @x, @y = 0, 0
    if data.nil?
    @data.lines_highlighted = []
    @data.fake_buffer = false
    @data.hlstacks, @data.classstacks, @data.tokens = [], [], []
    @data.dlog = EditorApp::DiffLogger::DifferenceLog.new app, self
    @data.is_paste_buffer = false
    end
    if !data.nil?
        @data = data
    end
    update_highlighter
    BufferListing::instance << self
    app.change_listeners << self.method(:notified_of_change)
end

Instance Attribute Details

#bnumObject

Returns the value of attribute bnum.



78
79
80
# File 'lib/buffer.rb', line 78

def bnum
  @bnum
end

#dataObject

Returns the value of attribute data.



74
75
76
# File 'lib/buffer.rb', line 74

def data
  @data
end

#got_a_scroll_alreadyObject

Returns the value of attribute got_a_scroll_already.



78
79
80
# File 'lib/buffer.rb', line 78

def got_a_scroll_already
  @got_a_scroll_already
end

#need_to_scrollObject

Returns the value of attribute need_to_scroll.



78
79
80
# File 'lib/buffer.rb', line 78

def need_to_scroll
  @need_to_scroll
end

#topObject

Returns the value of attribute top.



78
79
80
# File 'lib/buffer.rb', line 78

def top
  @top
end

#xObject

Returns the value of attribute x.



78
79
80
# File 'lib/buffer.rb', line 78

def x
  @x
end

#yObject

Returns the value of attribute y.



78
79
80
# File 'lib/buffer.rb', line 78

def y
  @y
end

Instance Method Details

#_invalidate_line_highlight(line_num) ⇒ Object

status_bar.render 0

@data.app.refresh_widgets
@data.app.display_cursor self


108
109
110
111
112
113
# File 'lib/buffer.rb', line 108

def _invalidate_line_highlight line_num
    raise if line_num.nil?
    fill_to_length line_num
    @data.highlight_cache[line_num] = nil
    update_status_bar_highlight_progress unless $test_case # hack-ish!
end

#axObject



85
86
87
# File 'lib/buffer.rb', line 85

def ax
    @data.app.end_char_mode ? @x + 1 : @x
end

#ensure_line_highlight(y) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/buffer.rb', line 114

def ensure_line_highlight y
    fill_to_length y
    pos_of_first_nil = @data.highlight_cache.index nil
    found = !pos_of_first_nil.nil?
    dbg(:dbg_highlight) { "ensure_line_highlight #{y}" }
    dbg(:hl) { "#{y} -- #{@data.highlight_cache[y].inspect} :: #{@data.lines[y].inspect}" }
    if (found and pos_of_first_nil <= y) or @data.highlight_cache[y].nil?
        pos_of_first_nil = [y, @data.highlight_cache.length].min
        # TODO - can become complex when we have multiple points of modification inside the visible screen
        (pos_of_first_nil..y).each {
           |line_num|
           tags = []
           dbg(:dbg_highlight) { "rehighlighting #{line_num}! - \"#{@data.lines[line_num]}\" from [(#{@data.lines.inspect})]" }
           state = @data.highlighter.get_highlight_state self, line_num
           @data.lines_highlighted << line_num
           @data.highlighter.highlight_line(self, @data.lines[line_num], line_num) {
              |color, bold, word|
              tags << [color, bold, word]
           }
           @data.highlight_cache[line_num] = tags
           break unless (@data.highlighter.should_continue_highlight_pass? self, line_num, state)
           update_status_bar_highlight_progress unless $test_case # hack-ish!
        }
        raise "failed to highlight requested line #{y}!" if @data.highlight_cache[y].nil?
        @data.highlight_cache[y+1] = nil
    end
end

#extend_array_to_num(arr, num) ⇒ Object



209
210
211
212
# File 'lib/buffer.rb', line 209

def extend_array_to_num arr, num
    diff = (num - arr.length)
    diff.times { arr << nil } if diff > 0
end

#fill_to_length(line_num) ⇒ Object



93
94
95
# File 'lib/buffer.rb', line 93

def fill_to_length line_num
    @data.highlight_cache << nil until @data.highlight_cache.length >= line_num
end

#first_non_highlighted_lineObject



79
80
81
82
83
84
# File 'lib/buffer.rb', line 79

def first_non_highlighted_line
    extend_array_to_num @data.hlstacks, @data.lines.length
    extend_array_to_num @data.classstacks, @data.lines.length
    extend_array_to_num @data.highlight_cache, @data.lines.length
    @data.highlight_cache.index nil
end

#fname=(val) ⇒ Object



205
206
207
208
# File 'lib/buffer.rb', line 205

def fname= val
    @data.fname = val
    update_highlighter
end

#invalidate_line_highlight(line_num) ⇒ Object



88
89
90
91
92
# File 'lib/buffer.rb', line 88

def invalidate_line_highlight line_num
    @data.app.mutex.synchronize {
        _invalidate_line_highlight line_num
    }
end

#iterate_line_highlight(y, line = nil) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/buffer.rb', line 141

def iterate_line_highlight y, line = nil
    if line.nil?
        if y > last_line_num
           yield Curses::COLOR_WHITE, false, " "
        else
        ensure_line_highlight y
        @data.highlight_cache[y].each { 
            |tag|
            color, bold, word = *tag 
            yield color, bold, word
        }
        end
    else
        @data.highlighter.highlight_line(self, line, y) {
           |*args|
           yield *args
        }
    end
end

#last_char_on_line(y) ⇒ Object



163
164
165
166
# File 'lib/buffer.rb', line 163

def last_char_on_line y
    raise "invalid y == #{y}" if last_line_num > @data.lines.length
    @data.lines[y].empty? ? 0 : @data.lines[y].length - 1
end

#last_line_numObject



160
161
162
# File 'lib/buffer.rb', line 160

def last_line_num
    @data.lines.empty? ? 0 : @data.lines.length - 1
end

#make_copyObject



167
168
169
# File 'lib/buffer.rb', line 167

def make_copy
    self.class.new @data.app, nil, @data
end

#move_to(x, y) ⇒ Object



259
260
261
262
263
264
265
266
267
268
# File 'lib/buffer.rb', line 259

def move_to x, y
    buffer = self
    buffer.x = x
    if y < buffer.top
        @data.app.scroll_up(buffer)   until @data.app.line_displayed?(buffer, y)
    elsif y >= (buffer.top + @data.app.screen_height)
        @data.app.scroll_down(buffer) until @data.app.line_displayed?(buffer, y)
    end
    buffer.y = y
end

#move_to_x(x) ⇒ Object



269
270
271
272
# File 'lib/buffer.rb', line 269

def move_to_x x
    buffer = self
    move_to x, buffer.y
end

#move_to_y(y) ⇒ Object



273
274
275
276
# File 'lib/buffer.rb', line 273

def move_to_y y
    buffer = self
    move_to buffer.x, y
end

#notified_of_change(change, direction) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/buffer.rb', line 213

def notified_of_change change, direction
    # TODO - optimisation: ability to cancel background thread by merging the two requests somehow
    sign = direction ? 1 : -1
    # return unless @data.highlighter.class.has_structure?
    if !change.is_a? EditorApp::DiffLogger::CursorPositionChange
        extend_array_to_num @data.hlstacks, change.line_num
        extend_array_to_num @data.classstacks, change.line_num
        extend_array_to_num @data.highlight_cache, change.line_num
    end
    case change
    when EditorApp::DiffLogger::InsertLineAfterChange
        if direction
            @data.hlstacks.insert_after change.line_num, nil
            @data.classstacks.insert_after change.line_num, nil
            @data.highlight_cache.insert_after change.line_num, nil
        else
            @data.hlstacks.delete_at change.line_num
            @data.classstacks.delete_at change.line_num
            @data.highlight_cache.delete_at change.line_num
        end
        # we invalidate the next line as thats where we insert
        invalidate_line_highlight change.line_num + 1
    when EditorApp::DiffLogger::RemoveLineChange
        if direction
            @data.hlstacks.insert_after change.line_num, nil
            @data.classstacks.insert_after change.line_num, nil
            @data.highlight_cache.insert_after change.line_num, nil
        else
            @data.hlstacks.delete_at change.line_num
            @data.classstacks.delete_at change.line_num
            @data.highlight_cache.delete_at change.line_num
        end
        # we invalidate the current line - note - what about removal of the last line in a document
        invalidate_line_highlight change.line_num
    when EditorApp::DiffLogger::ModifyLineChange 
        invalidate_line_highlight change.line_num
    when EditorApp::DiffLogger::CursorPositionChange
        ;
    else
        raise "unhandled change type!! #{change.type}"
    end
end

#out_of_bounds(y, x) ⇒ Object



277
278
279
# File 'lib/buffer.rb', line 277

def out_of_bounds y, x
    (x >= @data.lines[y].length)
end

#out_of_bounds2(y, x) ⇒ Object

TODO god this logic is ugly



281
282
283
# File 'lib/buffer.rb', line 281

def out_of_bounds2 y, x
    (x > @data.lines[y].length)
end

#textObject



284
285
286
# File 'lib/buffer.rb', line 284

def text
   (@data.lines.join "\n")
end

#update_highlighterObject



200
201
202
203
204
# File 'lib/buffer.rb', line 200

def update_highlighter
    hls = Highlighters::instance.registered_highlighters.sort_by { |plugin| -plugin.importance }
    hl_class = hls.detect { |hler| hler.can_highlight? self }
    @data.highlighter = hl_class.nil? ? nil : hl_class.new
end

#update_status_bar_highlight_progressObject



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/buffer.rb', line 96

def update_status_bar_highlight_progress
    status_bar = @data.app.widgets.detect { |sb| (sb.is_a? StatusBar) and (sb.buffer == self) }
    return if status_bar.nil? # minor hack - FIXME
    hl_len = [@data.highlight_cache.compact.length, @data.lines.length].min
    done_ratio = (hl_len / @data.lines.length.to_f)
    status_bar.highlight_progress = (done_ratio >= 1) ? nil : done_ratio
=begin
    status_bar.render 0
    @data.app.refresh_widgets
    @data.app.display_cursor self
=end
end