Run cargo fmt
This commit is contained in:
parent
00bc4d1e88
commit
8cc988d374
25 changed files with 732 additions and 731 deletions
|
|
@ -5,9 +5,9 @@ use alloc::string::String;
|
|||
use core::{cmp, iter::once};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::{Action, AttrsList, Buffer, BufferLine, Cursor, Edit, LayoutCursor};
|
||||
#[cfg(feature = "swash")]
|
||||
use crate::Color;
|
||||
use crate::{Action, AttrsList, Buffer, BufferLine, Cursor, Edit, LayoutCursor};
|
||||
|
||||
/// A wrapper of [`Buffer`] for easy editing
|
||||
pub struct Editor<'a> {
|
||||
|
|
@ -31,14 +31,17 @@ impl<'a> Editor<'a> {
|
|||
}
|
||||
|
||||
fn set_layout_cursor(&mut self, cursor: LayoutCursor) {
|
||||
let layout = self.buffer.line_layout(cursor.line).expect("layout not found");
|
||||
let layout = self
|
||||
.buffer
|
||||
.line_layout(cursor.line)
|
||||
.expect("layout not found");
|
||||
|
||||
let layout_line = match layout.get(cursor.layout) {
|
||||
Some(some) => some,
|
||||
None => match layout.last() {
|
||||
Some(some) => some,
|
||||
None => todo!("layout cursor in line with no layouts"),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let new_index = match layout_line.glyphs.get(cursor.glyph) {
|
||||
|
|
@ -47,7 +50,7 @@ impl<'a> Editor<'a> {
|
|||
Some(glyph) => glyph.end,
|
||||
//TODO: is this correct?
|
||||
None => 0,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if self.cursor.line != cursor.line || self.cursor.index != new_index {
|
||||
|
|
@ -217,7 +220,8 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
let after_len = after.text().len();
|
||||
|
||||
// Collect attributes
|
||||
let mut final_attrs = attrs_list.unwrap_or_else(|| AttrsList::new(line.attrs_list().get_span(line.text().len())));
|
||||
let mut final_attrs = attrs_list
|
||||
.unwrap_or_else(|| AttrsList::new(line.attrs_list().get_span(line.text().len())));
|
||||
|
||||
// Append the inserted text, line by line
|
||||
// we want to see a blank entry if the string ends with a newline
|
||||
|
|
@ -227,13 +231,23 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
let mut these_attrs = final_attrs.split_off(data_line.len());
|
||||
remaining_split_len -= data_line.len();
|
||||
core::mem::swap(&mut these_attrs, &mut final_attrs);
|
||||
line.append(BufferLine::new(data_line.strip_suffix(char::is_control).unwrap_or(data_line), these_attrs));
|
||||
line.append(BufferLine::new(
|
||||
data_line
|
||||
.strip_suffix(char::is_control)
|
||||
.unwrap_or(data_line),
|
||||
these_attrs,
|
||||
));
|
||||
} else {
|
||||
panic!("str::lines() did not yield any elements");
|
||||
}
|
||||
if let Some(data_line) = lines_iter.next_back() {
|
||||
remaining_split_len -= data_line.len();
|
||||
let mut tmp = BufferLine::new(data_line.strip_suffix(char::is_control).unwrap_or(data_line), final_attrs.split_off(remaining_split_len));
|
||||
let mut tmp = BufferLine::new(
|
||||
data_line
|
||||
.strip_suffix(char::is_control)
|
||||
.unwrap_or(data_line),
|
||||
final_attrs.split_off(remaining_split_len),
|
||||
);
|
||||
tmp.append(after);
|
||||
self.buffer.lines.insert(insert_line, tmp);
|
||||
self.cursor.line += 1;
|
||||
|
|
@ -242,7 +256,12 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
}
|
||||
for data_line in lines_iter.rev() {
|
||||
remaining_split_len -= data_line.len();
|
||||
let tmp = BufferLine::new(data_line.strip_suffix(char::is_control).unwrap_or(data_line), final_attrs.split_off(remaining_split_len));
|
||||
let tmp = BufferLine::new(
|
||||
data_line
|
||||
.strip_suffix(char::is_control)
|
||||
.unwrap_or(data_line),
|
||||
final_attrs.split_off(remaining_split_len),
|
||||
);
|
||||
self.buffer.lines.insert(insert_line, tmp);
|
||||
self.cursor.line += 1;
|
||||
}
|
||||
|
|
@ -278,7 +297,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.buffer.set_redraw(true);
|
||||
}
|
||||
self.cursor_x_opt = None;
|
||||
},
|
||||
}
|
||||
Action::Next => {
|
||||
let line = &mut self.buffer.lines[self.cursor.line];
|
||||
if self.cursor.index < line.text().len() {
|
||||
|
|
@ -295,9 +314,12 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.buffer.set_redraw(true);
|
||||
}
|
||||
self.cursor_x_opt = None;
|
||||
},
|
||||
}
|
||||
Action::Left => {
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl);
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line]
|
||||
.shape_opt()
|
||||
.as_ref()
|
||||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::Next);
|
||||
|
|
@ -305,9 +327,12 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.action(Action::Previous);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Right => {
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl);
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line]
|
||||
.shape_opt()
|
||||
.as_ref()
|
||||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::Previous);
|
||||
|
|
@ -315,14 +340,14 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.action(Action::Next);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Up => {
|
||||
//TODO: make this preserve X as best as possible!
|
||||
let mut cursor = self.buffer.layout_cursor(&self.cursor);
|
||||
|
||||
if self.cursor_x_opt.is_none() {
|
||||
self.cursor_x_opt = Some(
|
||||
cursor.glyph as i32 //TODO: glyph x position
|
||||
cursor.glyph as i32, //TODO: glyph x position
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -338,16 +363,20 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
}
|
||||
|
||||
self.set_layout_cursor(cursor);
|
||||
},
|
||||
}
|
||||
Action::Down => {
|
||||
//TODO: make this preserve X as best as possible!
|
||||
let mut cursor = self.buffer.layout_cursor(&self.cursor);
|
||||
|
||||
let layout_len = self.buffer.line_layout(cursor.line).expect("layout not found").len();
|
||||
let layout_len = self
|
||||
.buffer
|
||||
.line_layout(cursor.line)
|
||||
.expect("layout not found")
|
||||
.len();
|
||||
|
||||
if self.cursor_x_opt.is_none() {
|
||||
self.cursor_x_opt = Some(
|
||||
cursor.glyph as i32 //TODO: glyph x position
|
||||
cursor.glyph as i32, //TODO: glyph x position
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -363,13 +392,13 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
}
|
||||
|
||||
self.set_layout_cursor(cursor);
|
||||
},
|
||||
}
|
||||
Action::Home => {
|
||||
let mut cursor = self.buffer.layout_cursor(&self.cursor);
|
||||
cursor.glyph = 0;
|
||||
self.set_layout_cursor(cursor);
|
||||
self.cursor_x_opt = None;
|
||||
},
|
||||
}
|
||||
Action::End => {
|
||||
let mut cursor = self.buffer.layout_cursor(&self.cursor);
|
||||
cursor.glyph = usize::max_value();
|
||||
|
|
@ -388,10 +417,10 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
}
|
||||
Action::PageUp => {
|
||||
self.action(Action::Vertical(-self.buffer.size().1));
|
||||
},
|
||||
}
|
||||
Action::PageDown => {
|
||||
self.action(Action::Vertical(self.buffer.size().1));
|
||||
},
|
||||
}
|
||||
Action::Vertical(px) => {
|
||||
// TODO more efficient
|
||||
let lines = px / self.buffer.metrics().line_height;
|
||||
|
|
@ -404,16 +433,14 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.action(Action::Down);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Escape => {
|
||||
if self.select_opt.take().is_some() {
|
||||
self.buffer.set_redraw(true);
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Insert(character) => {
|
||||
if character.is_control()
|
||||
&& !['\t', '\n', '\u{92}'].contains(&character)
|
||||
{
|
||||
if character.is_control() && !['\t', '\n', '\u{92}'].contains(&character) {
|
||||
// Filter out special chars (except for tab), use Action instead
|
||||
log::debug!("Refusing to insert control character {:?}", character);
|
||||
} else if character == '\n' {
|
||||
|
|
@ -423,7 +450,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
let str_ref = character.encode_utf8(&mut str_buf);
|
||||
self.insert_string(str_ref, None);
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Enter => {
|
||||
self.delete_selection();
|
||||
|
||||
|
|
@ -433,7 +460,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.cursor.index = 0;
|
||||
|
||||
self.buffer.lines.insert(self.cursor.line, new_line);
|
||||
},
|
||||
}
|
||||
Action::Backspace => {
|
||||
if self.delete_selection() {
|
||||
// Deleted selection
|
||||
|
|
@ -472,7 +499,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
|
||||
line.append(old_line);
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Delete => {
|
||||
if self.delete_selection() {
|
||||
// Deleted selection
|
||||
|
|
@ -484,9 +511,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
.grapheme_indices(true)
|
||||
.take_while(|(i, _)| *i <= self.cursor.index)
|
||||
.last()
|
||||
.map(|(i, c)| {
|
||||
i..(i + c.len())
|
||||
});
|
||||
.map(|(i, c)| i..(i + c.len()));
|
||||
|
||||
if let Some(range) = range_opt {
|
||||
self.cursor.index = range.start;
|
||||
|
|
@ -504,7 +529,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
let old_line = self.buffer.lines.remove(self.cursor.line + 1);
|
||||
self.buffer.lines[self.cursor.line].append(old_line);
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Click { x, y } => {
|
||||
self.select_opt = None;
|
||||
|
||||
|
|
@ -514,7 +539,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.buffer.set_redraw(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Drag { x, y } => {
|
||||
if self.select_opt.is_none() {
|
||||
self.select_opt = Some(self.cursor);
|
||||
|
|
@ -527,7 +552,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.buffer.set_redraw(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::Scroll { lines } => {
|
||||
let mut scroll = self.buffer.scroll();
|
||||
scroll += lines;
|
||||
|
|
@ -573,7 +598,10 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.cursor_x_opt = None;
|
||||
}
|
||||
Action::LeftWord => {
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl);
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line]
|
||||
.shape_opt()
|
||||
.as_ref()
|
||||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::NextWord);
|
||||
|
|
@ -581,9 +609,12 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.action(Action::PreviousWord);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::RightWord => {
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl);
|
||||
let rtl_opt = self.buffer.lines[self.cursor.line]
|
||||
.shape_opt()
|
||||
.as_ref()
|
||||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::PreviousWord);
|
||||
|
|
@ -591,7 +622,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.action(Action::NextWord);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Action::BufferStart => {
|
||||
self.cursor.line = 0;
|
||||
self.cursor.index = 0;
|
||||
|
|
@ -628,7 +659,8 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
/// Draw the editor
|
||||
#[cfg(feature = "swash")]
|
||||
fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, mut f: F)
|
||||
where F: FnMut(i32, i32, u32, u32, Color)
|
||||
where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
let font_size = self.buffer.metrics().font_size;
|
||||
let line_height = self.buffer.metrics().line_height;
|
||||
|
|
@ -664,7 +696,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
if cursor.index == glyph.end {
|
||||
return Some((run.glyphs.len(), 0.0));
|
||||
}
|
||||
},
|
||||
}
|
||||
None => {
|
||||
return Some((0, 0.0));
|
||||
}
|
||||
|
|
@ -701,16 +733,14 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
let c_start = glyph.start + i;
|
||||
let c_end = glyph.start + i + c.len();
|
||||
if (start.line != line_i || c_end > start.index)
|
||||
&& (end.line != line_i || c_start < end.index) {
|
||||
&& (end.line != line_i || c_start < end.index)
|
||||
{
|
||||
range_opt = match range_opt.take() {
|
||||
Some((min, max)) => Some((
|
||||
cmp::min(min, c_x as i32),
|
||||
cmp::max(max, (c_x + c_w) as i32),
|
||||
)),
|
||||
None => Some((
|
||||
c_x as i32,
|
||||
(c_x + c_w) as i32,
|
||||
))
|
||||
None => Some((c_x as i32, (c_x + c_w) as i32)),
|
||||
};
|
||||
} else if let Some((min, max)) = range_opt.take() {
|
||||
f(
|
||||
|
|
@ -718,14 +748,14 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
line_y - font_size,
|
||||
cmp::max(0, max - min) as u32,
|
||||
line_height as u32,
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33)
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33),
|
||||
);
|
||||
}
|
||||
c_x += c_w;
|
||||
}
|
||||
}
|
||||
|
||||
if run.glyphs.is_empty() && end.line > line_i{
|
||||
if run.glyphs.is_empty() && end.line > line_i {
|
||||
// Highlight all of internal empty lines
|
||||
range_opt = Some((0, self.buffer.size().0));
|
||||
}
|
||||
|
|
@ -744,7 +774,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
line_y - font_size,
|
||||
cmp::max(0, max - min) as u32,
|
||||
line_height as u32,
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33)
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -760,7 +790,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
} else {
|
||||
(glyph.x + cursor_glyph_offset) as i32
|
||||
}
|
||||
},
|
||||
}
|
||||
None => match run.glyphs.last() {
|
||||
Some(glyph) => {
|
||||
// End of last glyph
|
||||
|
|
@ -769,21 +799,15 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
} else {
|
||||
(glyph.x + glyph.w) as i32
|
||||
}
|
||||
},
|
||||
}
|
||||
None => {
|
||||
// Start of empty line
|
||||
0
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
f(
|
||||
x,
|
||||
line_y - font_size,
|
||||
1,
|
||||
line_height as u32,
|
||||
color,
|
||||
);
|
||||
f(x, line_y - font_size, 1, line_height as u32, color);
|
||||
}
|
||||
|
||||
for glyph in run.glyphs.iter() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#[cfg(not(feature = "std"))]
|
||||
use alloc::string::String;
|
||||
|
||||
use crate::{AttrsList, Buffer, Cursor};
|
||||
#[cfg(feature = "swash")]
|
||||
use crate::Color;
|
||||
use crate::{AttrsList, Buffer, Cursor};
|
||||
|
||||
pub use self::editor::*;
|
||||
mod editor;
|
||||
|
|
@ -114,5 +114,6 @@ pub trait Edit<'a> {
|
|||
/// Draw the editor
|
||||
#[cfg(feature = "swash")]
|
||||
fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, f: F)
|
||||
where F: FnMut(i32, i32, u32, u32, Color);
|
||||
where
|
||||
F: FnMut(i32, i32, u32, u32, Color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,13 @@
|
|||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{
|
||||
string::String,
|
||||
vec::Vec,
|
||||
};
|
||||
use alloc::{string::String, vec::Vec};
|
||||
#[cfg(feature = "std")]
|
||||
use std::{
|
||||
fs,
|
||||
io,
|
||||
path::Path,
|
||||
};
|
||||
use std::{fs, io, path::Path};
|
||||
use syntect::highlighting::{
|
||||
FontStyle,
|
||||
Highlighter,
|
||||
HighlightState,
|
||||
RangedHighlightIterator,
|
||||
Theme,
|
||||
ThemeSet,
|
||||
};
|
||||
use syntect::parsing::{
|
||||
ParseState,
|
||||
ScopeStack,
|
||||
SyntaxReference,
|
||||
SyntaxSet,
|
||||
FontStyle, HighlightState, Highlighter, RangedHighlightIterator, Theme, ThemeSet,
|
||||
};
|
||||
use syntect::parsing::{ParseState, ScopeStack, SyntaxReference, SyntaxSet};
|
||||
|
||||
use crate::{
|
||||
Action,
|
||||
AttrsList,
|
||||
Buffer,
|
||||
Color,
|
||||
Cursor,
|
||||
Edit,
|
||||
Editor,
|
||||
Style,
|
||||
Weight,
|
||||
Wrap,
|
||||
};
|
||||
use crate::{Action, AttrsList, Buffer, Color, Cursor, Edit, Editor, Style, Weight, Wrap};
|
||||
|
||||
pub struct SyntaxSystem {
|
||||
pub syntax_set: SyntaxSet,
|
||||
|
|
@ -69,7 +41,11 @@ impl<'a> SyntaxEditor<'a> {
|
|||
/// A good default theme name is "base16-eighties.dark".
|
||||
///
|
||||
/// Returns None if theme not found
|
||||
pub fn new(buffer: Buffer<'a>, syntax_system: &'a SyntaxSystem, theme_name: &str) -> Option<Self> {
|
||||
pub fn new(
|
||||
buffer: Buffer<'a>,
|
||||
syntax_system: &'a SyntaxSystem,
|
||||
theme_name: &str,
|
||||
) -> Option<Self> {
|
||||
let editor = Editor::new(buffer);
|
||||
let syntax = syntax_system.syntax_set.find_syntax_plain_text();
|
||||
let theme = syntax_system.theme_set.themes.get(theme_name)?;
|
||||
|
|
@ -91,7 +67,11 @@ impl<'a> SyntaxEditor<'a> {
|
|||
///
|
||||
/// Returns an [`io::Error`] if reading the file fails
|
||||
#[cfg(feature = "std")]
|
||||
pub fn load_text<P: AsRef<Path>>(&mut self, path: P, attrs: crate::Attrs<'a>) -> io::Result<()> {
|
||||
pub fn load_text<P: AsRef<Path>>(
|
||||
&mut self,
|
||||
path: P,
|
||||
attrs: crate::Attrs<'a>,
|
||||
) -> io::Result<()> {
|
||||
let path = path.as_ref();
|
||||
|
||||
let text = fs::read_to_string(path)?;
|
||||
|
|
@ -119,12 +99,7 @@ impl<'a> SyntaxEditor<'a> {
|
|||
/// Get the default background color
|
||||
pub fn background_color(&self) -> Color {
|
||||
if let Some(background) = self.theme.settings.background {
|
||||
Color::rgba(
|
||||
background.r,
|
||||
background.g,
|
||||
background.b,
|
||||
background.a,
|
||||
)
|
||||
Color::rgba(background.r, background.g, background.b, background.a)
|
||||
} else {
|
||||
Color::rgb(0, 0, 0)
|
||||
}
|
||||
|
|
@ -133,12 +108,7 @@ impl<'a> SyntaxEditor<'a> {
|
|||
/// Get the default foreground (text) color
|
||||
pub fn foreground_color(&self) -> Color {
|
||||
if let Some(foreground) = self.theme.settings.foreground {
|
||||
Color::rgba(
|
||||
foreground.r,
|
||||
foreground.g,
|
||||
foreground.b,
|
||||
foreground.a,
|
||||
)
|
||||
Color::rgba(foreground.r, foreground.g, foreground.b, foreground.a)
|
||||
} else {
|
||||
Color::rgb(0xFF, 0xFF, 0xFF)
|
||||
}
|
||||
|
|
@ -175,21 +145,24 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
let mut highlighted = 0;
|
||||
for line_i in 0..buffer.lines.len() {
|
||||
let line = &mut buffer.lines[line_i];
|
||||
if ! line.is_reset() && line_i < self.syntax_cache.len() {
|
||||
if !line.is_reset() && line_i < self.syntax_cache.len() {
|
||||
continue;
|
||||
}
|
||||
highlighted += 1;
|
||||
|
||||
let (mut parse_state, mut highlight_state) = if line_i > 0 && line_i <= self.syntax_cache.len() {
|
||||
self.syntax_cache[line_i - 1].clone()
|
||||
} else {
|
||||
(
|
||||
ParseState::new(self.syntax),
|
||||
HighlightState::new(&self.highlighter, ScopeStack::new())
|
||||
)
|
||||
};
|
||||
let (mut parse_state, mut highlight_state) =
|
||||
if line_i > 0 && line_i <= self.syntax_cache.len() {
|
||||
self.syntax_cache[line_i - 1].clone()
|
||||
} else {
|
||||
(
|
||||
ParseState::new(self.syntax),
|
||||
HighlightState::new(&self.highlighter, ScopeStack::new()),
|
||||
)
|
||||
};
|
||||
|
||||
let ops = parse_state.parse_line(line.text(), &self.syntax_system.syntax_set).expect("failed to parse syntax");
|
||||
let ops = parse_state
|
||||
.parse_line(line.text(), &self.syntax_system.syntax_set)
|
||||
.expect("failed to parse syntax");
|
||||
let ranges = RangedHighlightIterator::new(
|
||||
&mut highlight_state,
|
||||
&ops,
|
||||
|
|
@ -219,8 +192,7 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
Weight::BOLD
|
||||
} else {
|
||||
Weight::NORMAL
|
||||
})
|
||||
//TODO: underline
|
||||
}), //TODO: underline
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +219,11 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
if highlighted > 0 {
|
||||
buffer.set_redraw(true);
|
||||
#[cfg(feature = "std")]
|
||||
log::debug!("Syntax highlighted {} lines in {:?}", highlighted, now.elapsed());
|
||||
log::debug!(
|
||||
"Syntax highlighted {} lines in {:?}",
|
||||
highlighted,
|
||||
now.elapsed()
|
||||
);
|
||||
}
|
||||
|
||||
self.editor.shape_as_needed();
|
||||
|
|
@ -272,7 +248,8 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
/// Draw the editor
|
||||
#[cfg(feature = "swash")]
|
||||
fn draw<F>(&self, cache: &mut crate::SwashCache, _color: Color, mut f: F)
|
||||
where F: FnMut(i32, i32, u32, u32, Color)
|
||||
where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
let size = self.buffer().size();
|
||||
f(0, 0, size.0 as u32, size.1 as u32, self.background_color());
|
||||
|
|
|
|||
100
src/edit/vi.rs
100
src/edit/vi.rs
|
|
@ -2,15 +2,7 @@ use alloc::string::String;
|
|||
use core::cmp;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::{
|
||||
Action,
|
||||
AttrsList,
|
||||
Buffer,
|
||||
Color,
|
||||
Cursor,
|
||||
Edit,
|
||||
SyntaxEditor,
|
||||
};
|
||||
use crate::{Action, AttrsList, Buffer, Color, Cursor, Edit, SyntaxEditor};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum Mode {
|
||||
|
|
@ -36,7 +28,11 @@ impl<'a> ViEditor<'a> {
|
|||
|
||||
/// Load text from a file, and also set syntax to the best option
|
||||
#[cfg(feature = "std")]
|
||||
pub fn load_text<P: AsRef<std::path::Path>>(&mut self, path: P, attrs: crate::Attrs<'a>) -> std::io::Result<()> {
|
||||
pub fn load_text<P: AsRef<std::path::Path>>(
|
||||
&mut self,
|
||||
path: P,
|
||||
attrs: crate::Attrs<'a>,
|
||||
) -> std::io::Result<()> {
|
||||
self.editor.load_text(path, attrs)
|
||||
}
|
||||
|
||||
|
|
@ -98,12 +94,12 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
'a' => {
|
||||
self.editor.action(Action::Right);
|
||||
self.mode = Mode::Insert;
|
||||
},
|
||||
}
|
||||
// Enter insert mode at end of line
|
||||
'A' => {
|
||||
self.editor.action(Action::End);
|
||||
self.mode = Mode::Insert;
|
||||
},
|
||||
}
|
||||
// Change mode
|
||||
'c' => {
|
||||
if self.editor.select_opt().is_some() {
|
||||
|
|
@ -112,7 +108,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
} else {
|
||||
//TODO: change to next cursor movement
|
||||
}
|
||||
},
|
||||
}
|
||||
// Delete mode
|
||||
'd' => {
|
||||
if self.editor.select_opt().is_some() {
|
||||
|
|
@ -120,11 +116,11 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
} else {
|
||||
//TODO: delete to next cursor movement
|
||||
}
|
||||
},
|
||||
}
|
||||
// Enter insert mode at cursor
|
||||
'i' => {
|
||||
self.mode = Mode::Insert;
|
||||
},
|
||||
}
|
||||
// Enter insert mode at start of line
|
||||
'I' => {
|
||||
//TODO: soft home, skip whitespace
|
||||
|
|
@ -136,7 +132,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
self.editor.action(Action::End);
|
||||
self.editor.action(Action::Enter);
|
||||
self.mode = Mode::Insert;
|
||||
},
|
||||
}
|
||||
// Create line before and enter insert mode
|
||||
'O' => {
|
||||
self.editor.action(Action::Home);
|
||||
|
|
@ -144,7 +140,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
self.editor.shape_as_needed(); // TODO: do not require this?
|
||||
self.editor.action(Action::Up);
|
||||
self.mode = Mode::Insert;
|
||||
},
|
||||
}
|
||||
// Left
|
||||
'h' => self.editor.action(Action::Left),
|
||||
// Top of screen
|
||||
|
|
@ -166,7 +162,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
} else {
|
||||
self.editor.set_select_opt(Some(self.editor.cursor()));
|
||||
}
|
||||
},
|
||||
}
|
||||
// Enter line visual mode
|
||||
'V' => {
|
||||
if self.editor.select_opt().is_some() {
|
||||
|
|
@ -177,7 +173,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
//TODO: set cursor_x_opt to max
|
||||
self.editor.action(Action::End);
|
||||
}
|
||||
},
|
||||
}
|
||||
// Remove character at cursor
|
||||
'x' => self.editor.action(Action::Delete),
|
||||
// Remove character before cursor
|
||||
|
|
@ -192,15 +188,15 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
// Enter command mode
|
||||
':' => {
|
||||
self.mode = Mode::Command;
|
||||
},
|
||||
}
|
||||
// Enter search mode
|
||||
'/' => {
|
||||
self.mode = Mode::Search;
|
||||
},
|
||||
}
|
||||
// Enter search backwards mode
|
||||
'?' => {
|
||||
self.mode = Mode::SearchBackwards;
|
||||
},
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
_ => self.editor.action(action),
|
||||
|
|
@ -213,13 +209,13 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
self.editor.action(Action::Left);
|
||||
}
|
||||
self.mode = Mode::Normal;
|
||||
},
|
||||
}
|
||||
_ => self.editor.action(action),
|
||||
},
|
||||
_ => {
|
||||
//TODO: other modes
|
||||
self.mode = Mode::Normal;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if self.mode != old_mode {
|
||||
|
|
@ -229,7 +225,8 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
|
||||
#[cfg(feature = "swash")]
|
||||
fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, mut f: F)
|
||||
where F: FnMut(i32, i32, u32, u32, Color)
|
||||
where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
let font_size = self.buffer().metrics().font_size;
|
||||
let line_height = self.buffer().metrics().line_height;
|
||||
|
|
@ -266,7 +263,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
if cursor.index == glyph.end {
|
||||
return Some((run.glyphs.len(), 0.0, default_width));
|
||||
}
|
||||
},
|
||||
}
|
||||
None => {
|
||||
return Some((0, 0.0, default_width));
|
||||
}
|
||||
|
|
@ -303,16 +300,14 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
let c_start = glyph.start + i;
|
||||
let c_end = glyph.start + i + c.len();
|
||||
if (start.line != line_i || c_end > start.index)
|
||||
&& (end.line != line_i || c_start < end.index) {
|
||||
&& (end.line != line_i || c_start < end.index)
|
||||
{
|
||||
range_opt = match range_opt.take() {
|
||||
Some((min, max)) => Some((
|
||||
cmp::min(min, c_x as i32),
|
||||
cmp::max(max, (c_x + c_w) as i32),
|
||||
)),
|
||||
None => Some((
|
||||
c_x as i32,
|
||||
(c_x + c_w) as i32,
|
||||
))
|
||||
None => Some((c_x as i32, (c_x + c_w) as i32)),
|
||||
};
|
||||
} else if let Some((min, max)) = range_opt.take() {
|
||||
f(
|
||||
|
|
@ -320,14 +315,14 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
line_y - font_size,
|
||||
cmp::max(0, max - min) as u32,
|
||||
line_height as u32,
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33)
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33),
|
||||
);
|
||||
}
|
||||
c_x += c_w;
|
||||
}
|
||||
}
|
||||
|
||||
if run.glyphs.is_empty() && end.line > line_i{
|
||||
if run.glyphs.is_empty() && end.line > line_i {
|
||||
// Highlight all of internal empty lines
|
||||
range_opt = Some((0, self.buffer().size().0));
|
||||
}
|
||||
|
|
@ -346,18 +341,20 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
line_y - font_size,
|
||||
cmp::max(0, max - min) as u32,
|
||||
line_height as u32,
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33)
|
||||
Color::rgba(color.r(), color.g(), color.b(), 0x33),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw cursor
|
||||
if let Some((cursor_glyph, cursor_glyph_offset, cursor_glyph_width)) = cursor_glyph_opt(&self.cursor()) {
|
||||
if let Some((cursor_glyph, cursor_glyph_offset, cursor_glyph_width)) =
|
||||
cursor_glyph_opt(&self.cursor())
|
||||
{
|
||||
let block_cursor = match self.mode {
|
||||
Mode::Normal => true,
|
||||
Mode::Insert => false,
|
||||
_ => true /*TODO: determine block cursor in other modes*/
|
||||
_ => true, /*TODO: determine block cursor in other modes*/
|
||||
};
|
||||
|
||||
let (start_x, end_x) = match run.glyphs.get(cursor_glyph) {
|
||||
|
|
@ -366,38 +363,33 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
if glyph.level.is_rtl() {
|
||||
(
|
||||
(glyph.x + glyph.w - cursor_glyph_offset) as i32,
|
||||
(glyph.x + glyph.w - cursor_glyph_offset - cursor_glyph_width) as i32,
|
||||
(glyph.x + glyph.w - cursor_glyph_offset - cursor_glyph_width)
|
||||
as i32,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
(glyph.x + cursor_glyph_offset) as i32,
|
||||
(glyph.x + cursor_glyph_offset + cursor_glyph_width) as i32
|
||||
(glyph.x + cursor_glyph_offset + cursor_glyph_width) as i32,
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
None => match run.glyphs.last() {
|
||||
Some(glyph) => {
|
||||
// End of last glyph
|
||||
if glyph.level.is_rtl() {
|
||||
(
|
||||
glyph.x as i32,
|
||||
(glyph.x - cursor_glyph_width) as i32
|
||||
)
|
||||
(glyph.x as i32, (glyph.x - cursor_glyph_width) as i32)
|
||||
} else {
|
||||
(
|
||||
(glyph.x + glyph.w) as i32,
|
||||
(glyph.x + glyph.w + cursor_glyph_width) as i32
|
||||
(glyph.x + glyph.w + cursor_glyph_width) as i32,
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
None => {
|
||||
// Start of empty line
|
||||
(
|
||||
0,
|
||||
cursor_glyph_width as i32
|
||||
)
|
||||
(0, cursor_glyph_width as i32)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if block_cursor {
|
||||
|
|
@ -411,13 +403,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
Color::rgba(color.r(), color.g(), color.b(), 0x33),
|
||||
);
|
||||
} else {
|
||||
f(
|
||||
start_x,
|
||||
line_y - font_size,
|
||||
1,
|
||||
line_height as u32,
|
||||
color,
|
||||
);
|
||||
f(start_x, line_y - font_size, 1, line_height as u32, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue