@@ -1,5 +1,5 @@
1use clap::ArgMatches as Args;
1use clap::ArgMatches as Args;
2−use helix_core::{state::coords_at_pos, state::Mode, syntax::HighlightEvent, Range, State};
2+use helix_core::{state::Mode, syntax::HighlightEvent, Range, State};
3use helix_view::{commands, keymap, View};
3use helix_view::{commands, keymap, View};
@@ -24,6 +24,8 @@ use crossterm::{
25use tui::{backend::CrosstermBackend, buffer::Buffer as Surface, layout::Rect, style::Style};
25use tui::{backend::CrosstermBackend, buffer::Buffer as Surface, layout::Rect, style::Style};
27+const TAB_WIDTH: usize = 4;
27type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
29type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
29static EX: smol::Executor = smol::Executor::new();
31static EX: smol::Executor = smol::Executor::new();
@@ -85,10 +87,7 @@ impl Editor {
85 // TODO: inefficient, should feed chunks.iter() to tree_sitter.parse_with(|offset, pos|)
87 // TODO: inefficient, should feed chunks.iter() to tree_sitter.parse_with(|offset, pos|)
86 let source_code = view.state.doc().to_string();
88 let source_code = view.state.doc().to_string();
88− let last_line = std::cmp::min(
90+ let last_line = view.last_line(viewport);
89− (view.first_line + viewport.height - 1) as usize,
90− view.state.doc().len_lines() - 1,
93 let range = {
92 let range = {
94 // calculate viewport byte ranges
93 // calculate viewport byte ranges
@@ -172,6 +171,8 @@ impl Editor {
172 if line >= viewport.height {
171 if line >= viewport.height {
173 break 'outer;
172 break 'outer;
174+ } else if grapheme == "\t" {
175+ visual_x += (TAB_WIDTH as u16);
176 // Cow will prevent allocations if span contained in a single slice
177 // Cow will prevent allocations if span contained in a single slice
177 // which should really be the majority case
178 // which should really be the majority case
@@ -281,12 +282,16 @@ impl Editor {
282 // render the cursor
283 // render the cursor
283 let pos = view.state.selection().cursor();
284 let pos = view.state.selection().cursor();
284− let coords = coords_at_pos(&view.state.doc().slice(..), pos);
287+ .screen_coords_at_pos(&view.state.doc().slice(..), pos, area)
288+ .expect("Cursor is out of bounds.");
285 execute!(
290 execute!(
287 cursor::MoveTo(
292 cursor::MoveTo(
288− coords.col as u16 + viewport.x,
293+ pos.col as u16 + viewport.x,
289− coords.row as u16 - view.first_line + viewport.y,
294+ pos.row as u16 - view.first_line + viewport.y,