@@ -69,15 +69,15 @@ impl EditorView {
69 is_focused: bool,
69 is_focused: bool,
71 // TODO: inefficient, should feed chunks.iter() to tree_sitter.parse_with(|offset, pos|)
71 // TODO: inefficient, should feed chunks.iter() to tree_sitter.parse_with(|offset, pos|)
72− let source_code = view.doc.text().to_string();
72+ let text = view.doc.text();
73+ let source_code = text.to_string();
74 let last_line = view.last_line();
75 let last_line = view.last_line();
76 let range = {
77 let range = {
77 // calculate viewport byte ranges
78 // calculate viewport byte ranges
78− let start = view.doc.text().line_to_byte(view.first_line);
79+ let start = text.line_to_byte(view.first_line);
79− let end = view.doc.text().line_to_byte(last_line)
80+ let end = text.line_to_byte(last_line) + text.line(last_line).len_bytes();
80− + view.doc.text().line(last_line).len_bytes();
82 start..end
82 start..end
@@ -126,10 +126,12 @@ impl EditorView {
126 HighlightEvent::Source { start, end } => {
126 HighlightEvent::Source { start, end } => {
127 // TODO: filter out spans out of viewport for now..
127 // TODO: filter out spans out of viewport for now..
129− let start = view.doc.text().byte_to_char(start);
129+ // TODO: do these before iterating
130− let end = view.doc.text().byte_to_char(end); // <-- index 744, len 743
130+ let text = view.doc.text();
131+ let start = text.byte_to_char(start);
132+ let end = text.byte_to_char(end);
132− let text = view.doc.text().slice(start..end);
134+ let text = text.slice(start..end);
134 use helix_core::graphemes::{grapheme_width, RopeGraphemes};
136 use helix_core::graphemes::{grapheme_width, RopeGraphemes};
@@ -141,6 +143,7 @@ impl EditorView {
141 // TODO: we could render the text to a surface, then cache that, that
143 // TODO: we could render the text to a surface, then cache that, that
142 // way if only the selection/cursor changes we can copy from cache
144 // way if only the selection/cursor changes we can copy from cache
143 // and paint the new cursor.
145 // and paint the new cursor.
146+ // We could keep a single resizable surface on the View for that.
145 let mut char_index = start;
148 let mut char_index = start;
@@ -159,6 +162,13 @@ impl EditorView {
159 } else if grapheme == "\t" {
162 } else if grapheme == "\t" {
160 visual_x += (TAB_WIDTH as u16);
163 visual_x += (TAB_WIDTH as u16);
165+ if visual_x >= viewport.width {
166+ // if we're offscreen just keep going until we hit a new line
167+ // TODO: will need tweaking when we also take into account
168+ // horizontal scrolling
162 // Cow will prevent allocations if span contained in a single slice
172 // Cow will prevent allocations if span contained in a single slice
163 // which should really be the majority case
173 // which should really be the majority case
164 let grapheme = Cow::from(grapheme);
174 let grapheme = Cow::from(grapheme);
@@ -198,16 +208,12 @@ impl EditorView {
199 // TODO: paint cursor heads except primary
209 // TODO: paint cursor heads except primary
201− // HAXX: we don't render the char if it's offscreen. This should be
202− // skipped in a better way much earlier
203− if visual_x < viewport.width {
204− surface.set_string(
211+ surface.set_string(
205− viewport.x + visual_x,
212+ viewport.x + visual_x,
206− viewport.y + line,
213+ viewport.y + line,
207− grapheme,
214+ grapheme,
212 visual_x += width;
218 visual_x += width;