Extract borrow of FontSystem from Buffer
This commit is contained in:
parent
bff5aaaea3
commit
057b5b6fa9
12 changed files with 381 additions and 216 deletions
|
|
@ -10,20 +10,22 @@ use unicode_segmentation::UnicodeSegmentation;
|
|||
|
||||
#[cfg(feature = "swash")]
|
||||
use crate::Color;
|
||||
use crate::{Action, Affinity, AttrsList, Buffer, BufferLine, Cursor, Edit, LayoutCursor};
|
||||
use crate::{
|
||||
Action, Affinity, AttrsList, Buffer, BufferLine, Cursor, Edit, FontSystem, LayoutCursor,
|
||||
};
|
||||
|
||||
/// A wrapper of [`Buffer`] for easy editing
|
||||
pub struct Editor<'a> {
|
||||
buffer: Buffer<'a>,
|
||||
pub struct Editor {
|
||||
buffer: Buffer,
|
||||
cursor: Cursor,
|
||||
cursor_x_opt: Option<i32>,
|
||||
select_opt: Option<Cursor>,
|
||||
cursor_moved: bool,
|
||||
}
|
||||
|
||||
impl<'a> Editor<'a> {
|
||||
impl Editor {
|
||||
/// Create a new [`Editor`] with the provided [`Buffer`]
|
||||
pub fn new(buffer: Buffer<'a>) -> Self {
|
||||
pub fn new(buffer: Buffer) -> Self {
|
||||
Self {
|
||||
buffer,
|
||||
cursor: Cursor::default(),
|
||||
|
|
@ -33,10 +35,10 @@ impl<'a> Editor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_layout_cursor(&mut self, cursor: LayoutCursor) {
|
||||
fn set_layout_cursor(&mut self, font_system: &FontSystem, cursor: LayoutCursor) {
|
||||
let layout = self
|
||||
.buffer
|
||||
.line_layout(cursor.line)
|
||||
.line_layout(font_system, cursor.line)
|
||||
.expect("layout not found");
|
||||
|
||||
let layout_line = match layout.get(cursor.layout) {
|
||||
|
|
@ -68,12 +70,12 @@ impl<'a> Editor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Edit<'a> for Editor<'a> {
|
||||
fn buffer(&self) -> &Buffer<'a> {
|
||||
impl Edit for Editor {
|
||||
fn buffer(&self) -> &Buffer {
|
||||
&self.buffer
|
||||
}
|
||||
|
||||
fn buffer_mut(&mut self) -> &mut Buffer<'a> {
|
||||
fn buffer_mut(&mut self) -> &mut Buffer {
|
||||
&mut self.buffer
|
||||
}
|
||||
|
||||
|
|
@ -92,12 +94,12 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn shape_as_needed(&mut self) {
|
||||
fn shape_as_needed(&mut self, font_system: &FontSystem) {
|
||||
if self.cursor_moved {
|
||||
self.buffer.shape_until_cursor(self.cursor);
|
||||
self.buffer.shape_until_cursor(font_system, self.cursor);
|
||||
self.cursor_moved = false;
|
||||
} else {
|
||||
self.buffer.shape_until_scroll();
|
||||
self.buffer.shape_until_scroll(font_system);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,7 +281,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.cursor.index = self.buffer.lines[self.cursor.line].text().len() - after_len;
|
||||
}
|
||||
|
||||
fn action(&mut self, action: Action) {
|
||||
fn action(&mut self, font_system: &FontSystem, action: Action) {
|
||||
let old_cursor = self.cursor;
|
||||
|
||||
match action {
|
||||
|
|
@ -333,9 +335,9 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::Next);
|
||||
self.action(font_system, Action::Next);
|
||||
} else {
|
||||
self.action(Action::Previous);
|
||||
self.action(font_system, Action::Previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -346,9 +348,9 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::Previous);
|
||||
self.action(font_system, Action::Previous);
|
||||
} else {
|
||||
self.action(Action::Next);
|
||||
self.action(font_system, Action::Next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -373,7 +375,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
cursor.glyph = cursor_x as usize; //TODO: glyph x position
|
||||
}
|
||||
|
||||
self.set_layout_cursor(cursor);
|
||||
self.set_layout_cursor(font_system, cursor);
|
||||
}
|
||||
Action::Down => {
|
||||
//TODO: make this preserve X as best as possible!
|
||||
|
|
@ -381,7 +383,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
|
||||
let layout_len = self
|
||||
.buffer
|
||||
.line_layout(cursor.line)
|
||||
.line_layout(font_system, cursor.line)
|
||||
.expect("layout not found")
|
||||
.len();
|
||||
|
||||
|
|
@ -402,18 +404,18 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
cursor.glyph = cursor_x as usize; //TODO: glyph x position
|
||||
}
|
||||
|
||||
self.set_layout_cursor(cursor);
|
||||
self.set_layout_cursor(font_system, cursor);
|
||||
}
|
||||
Action::Home => {
|
||||
let mut cursor = self.buffer.layout_cursor(&self.cursor);
|
||||
cursor.glyph = 0;
|
||||
self.set_layout_cursor(cursor);
|
||||
self.set_layout_cursor(font_system, cursor);
|
||||
self.cursor_x_opt = None;
|
||||
}
|
||||
Action::End => {
|
||||
let mut cursor = self.buffer.layout_cursor(&self.cursor);
|
||||
cursor.glyph = usize::max_value();
|
||||
self.set_layout_cursor(cursor);
|
||||
self.set_layout_cursor(font_system, cursor);
|
||||
self.cursor_x_opt = None;
|
||||
}
|
||||
Action::ParagraphStart => {
|
||||
|
|
@ -427,10 +429,10 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
self.buffer.set_redraw(true);
|
||||
}
|
||||
Action::PageUp => {
|
||||
self.action(Action::Vertical(-self.buffer.size().1 as i32));
|
||||
self.action(font_system, Action::Vertical(-self.buffer.size().1 as i32));
|
||||
}
|
||||
Action::PageDown => {
|
||||
self.action(Action::Vertical(self.buffer.size().1 as i32));
|
||||
self.action(font_system, Action::Vertical(self.buffer.size().1 as i32));
|
||||
}
|
||||
Action::Vertical(px) => {
|
||||
// TODO more efficient
|
||||
|
|
@ -438,12 +440,12 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
match lines.cmp(&0) {
|
||||
Ordering::Less => {
|
||||
for _ in 0..-lines {
|
||||
self.action(Action::Up);
|
||||
self.action(font_system, Action::Up);
|
||||
}
|
||||
}
|
||||
Ordering::Greater => {
|
||||
for _ in 0..lines {
|
||||
self.action(Action::Down);
|
||||
self.action(font_system, Action::Down);
|
||||
}
|
||||
}
|
||||
Ordering::Equal => {}
|
||||
|
|
@ -459,7 +461,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
// Filter out special chars (except for tab), use Action instead
|
||||
log::debug!("Refusing to insert control character {:?}", character);
|
||||
} else if character == '\n' {
|
||||
self.action(Action::Enter);
|
||||
self.action(font_system, Action::Enter);
|
||||
} else {
|
||||
let mut str_buf = [0u8; 8];
|
||||
let str_ref = character.encode_utf8(&mut str_buf);
|
||||
|
|
@ -619,9 +621,9 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::NextWord);
|
||||
self.action(font_system, Action::NextWord);
|
||||
} else {
|
||||
self.action(Action::PreviousWord);
|
||||
self.action(font_system, Action::PreviousWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -632,9 +634,9 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
.map(|shape| shape.rtl);
|
||||
if let Some(rtl) = rtl_opt {
|
||||
if rtl {
|
||||
self.action(Action::PreviousWord);
|
||||
self.action(font_system, Action::PreviousWord);
|
||||
} else {
|
||||
self.action(Action::NextWord);
|
||||
self.action(font_system, Action::NextWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -673,8 +675,13 @@ 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
|
||||
fn draw<F>(
|
||||
&self,
|
||||
font_system: &FontSystem,
|
||||
cache: &mut crate::SwashCache,
|
||||
color: Color,
|
||||
mut f: F,
|
||||
) where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
let font_size = self.buffer.metrics().font_size;
|
||||
|
|
@ -833,14 +840,9 @@ impl<'a> Edit<'a> for Editor<'a> {
|
|||
None => color,
|
||||
};
|
||||
|
||||
cache.with_pixels(
|
||||
self.buffer.font_system(),
|
||||
cache_key,
|
||||
glyph_color,
|
||||
|x, y, color| {
|
||||
f(x_int + x, line_y as i32 + y_int + y, 1, 1, color);
|
||||
},
|
||||
);
|
||||
cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| {
|
||||
f(x_int + x, line_y as i32 + y_int + y, 1, 1, color);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use alloc::string::String;
|
|||
|
||||
#[cfg(feature = "swash")]
|
||||
use crate::Color;
|
||||
use crate::{AttrsList, Buffer, Cursor};
|
||||
use crate::{AttrsList, BorrowedWithFontSystem, Buffer, Cursor, FontSystem};
|
||||
|
||||
pub use self::editor::*;
|
||||
mod editor;
|
||||
|
|
@ -78,12 +78,25 @@ pub enum Action {
|
|||
}
|
||||
|
||||
/// A trait to allow easy replacements of [`Editor`], like `SyntaxEditor`
|
||||
pub trait Edit<'a> {
|
||||
pub trait Edit {
|
||||
fn borrow_with<'a>(
|
||||
&'a mut self,
|
||||
font_system: &'a FontSystem,
|
||||
) -> BorrowedWithFontSystem<'a, Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
BorrowedWithFontSystem {
|
||||
inner: self,
|
||||
font_system,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the internal [`Buffer`]
|
||||
fn buffer(&self) -> &Buffer<'a>;
|
||||
fn buffer(&self) -> &Buffer;
|
||||
|
||||
/// Get the internal [`Buffer`], mutably
|
||||
fn buffer_mut(&mut self) -> &mut Buffer<'a>;
|
||||
fn buffer_mut(&mut self) -> &mut Buffer;
|
||||
|
||||
/// Get the current cursor position
|
||||
fn cursor(&self) -> Cursor;
|
||||
|
|
@ -95,7 +108,7 @@ pub trait Edit<'a> {
|
|||
fn set_select_opt(&mut self, select_opt: Option<Cursor>);
|
||||
|
||||
/// Shape lines until scroll, after adjusting scroll if the cursor moved
|
||||
fn shape_as_needed(&mut self);
|
||||
fn shape_as_needed(&mut self, font_system: &FontSystem);
|
||||
|
||||
/// Copy selection
|
||||
fn copy_selection(&mut self) -> Option<String>;
|
||||
|
|
@ -109,11 +122,40 @@ pub trait Edit<'a> {
|
|||
fn insert_string(&mut self, data: &str, attrs_list: Option<AttrsList>);
|
||||
|
||||
/// Perform an [Action] on the editor
|
||||
fn action(&mut self, action: Action);
|
||||
fn action(&mut self, font_system: &FontSystem, action: Action);
|
||||
|
||||
/// Draw the editor
|
||||
#[cfg(feature = "swash")]
|
||||
fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, f: F)
|
||||
fn draw<F>(&self, font_system: &FontSystem, cache: &mut crate::SwashCache, color: Color, f: F)
|
||||
where
|
||||
F: FnMut(i32, i32, u32, u32, Color);
|
||||
}
|
||||
|
||||
impl<'a, T: Edit> BorrowedWithFontSystem<'a, T> {
|
||||
/// Get the internal [`Buffer`], mutably
|
||||
pub fn buffer_mut(&mut self) -> BorrowedWithFontSystem<Buffer> {
|
||||
BorrowedWithFontSystem {
|
||||
inner: self.inner.buffer_mut(),
|
||||
font_system: self.font_system,
|
||||
}
|
||||
}
|
||||
|
||||
/// Shape lines until scroll, after adjusting scroll if the cursor moved
|
||||
pub fn shape_as_needed(&mut self) {
|
||||
self.inner.shape_as_needed(self.font_system);
|
||||
}
|
||||
|
||||
/// Perform an [Action] on the editor
|
||||
pub fn action(&mut self, action: Action) {
|
||||
self.inner.action(self.font_system, action);
|
||||
}
|
||||
|
||||
/// Draw the editor
|
||||
#[cfg(feature = "swash")]
|
||||
pub fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, f: F)
|
||||
where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
self.inner.draw(self.font_system, cache, color, f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ use syntect::highlighting::{
|
|||
};
|
||||
use syntect::parsing::{ParseState, ScopeStack, SyntaxReference, SyntaxSet};
|
||||
|
||||
use crate::{Action, AttrsList, Buffer, Color, Cursor, Edit, Editor, Style, Weight, Wrap};
|
||||
use crate::{
|
||||
Action, AttrsList, BorrowedWithFontSystem, Buffer, Color, Cursor, Edit, Editor, FontSystem,
|
||||
Style, Weight, Wrap,
|
||||
};
|
||||
|
||||
pub struct SyntaxSystem {
|
||||
pub syntax_set: SyntaxSet,
|
||||
|
|
@ -27,7 +30,7 @@ impl SyntaxSystem {
|
|||
|
||||
/// A wrapper of [`Editor`] with syntax highlighting provided by [`SyntaxSystem`]
|
||||
pub struct SyntaxEditor<'a> {
|
||||
editor: Editor<'a>,
|
||||
editor: Editor,
|
||||
syntax_system: &'a SyntaxSystem,
|
||||
syntax: &'a SyntaxReference,
|
||||
theme: &'a Theme,
|
||||
|
|
@ -41,11 +44,7 @@ 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, 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)?;
|
||||
|
|
@ -61,21 +60,17 @@ impl<'a> SyntaxEditor<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Load text from a file, and also set syntax to the best option
|
||||
///
|
||||
/// ## Errors
|
||||
///
|
||||
/// Returns an [`io::Error`] if reading the file fails
|
||||
#[cfg(feature = "std")]
|
||||
pub fn load_text<P: AsRef<Path>>(
|
||||
pub(crate) fn load_text<P: AsRef<Path>>(
|
||||
&mut self,
|
||||
font_system: &FontSystem,
|
||||
path: P,
|
||||
attrs: crate::Attrs<'a>,
|
||||
attrs: crate::Attrs,
|
||||
) -> io::Result<()> {
|
||||
let path = path.as_ref();
|
||||
|
||||
let text = fs::read_to_string(path)?;
|
||||
self.editor.buffer_mut().set_text(&text, attrs);
|
||||
self.editor.buffer_mut().set_text(font_system, &text, attrs);
|
||||
|
||||
//TODO: re-use text
|
||||
self.syntax = match self.syntax_system.syntax_set.find_syntax_for_file(path) {
|
||||
|
|
@ -115,12 +110,12 @@ impl<'a> SyntaxEditor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
||||
fn buffer(&self) -> &Buffer<'a> {
|
||||
impl<'a> Edit for SyntaxEditor<'a> {
|
||||
fn buffer(&self) -> &Buffer {
|
||||
self.editor.buffer()
|
||||
}
|
||||
|
||||
fn buffer_mut(&mut self) -> &mut Buffer<'a> {
|
||||
fn buffer_mut(&mut self) -> &mut Buffer {
|
||||
self.editor.buffer_mut()
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +131,7 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
self.editor.set_select_opt(select_opt);
|
||||
}
|
||||
|
||||
fn shape_as_needed(&mut self) {
|
||||
fn shape_as_needed(&mut self, font_system: &FontSystem) {
|
||||
#[cfg(feature = "std")]
|
||||
let now = std::time::Instant::now();
|
||||
|
||||
|
|
@ -201,7 +196,7 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
line.set_wrap(Wrap::Word);
|
||||
|
||||
//TODO: efficiently do syntax highlighting without having to shape whole buffer
|
||||
buffer.line_shape(line_i);
|
||||
buffer.line_shape(font_system, line_i);
|
||||
|
||||
let cache_item = (parse_state.clone(), highlight_state.clone());
|
||||
if line_i < self.syntax_cache.len() {
|
||||
|
|
@ -226,7 +221,7 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
self.editor.shape_as_needed();
|
||||
self.editor.shape_as_needed(font_system);
|
||||
}
|
||||
|
||||
fn copy_selection(&mut self) -> Option<String> {
|
||||
|
|
@ -241,18 +236,36 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
|||
self.editor.insert_string(data, attrs_list);
|
||||
}
|
||||
|
||||
fn action(&mut self, action: Action) {
|
||||
self.editor.action(action);
|
||||
fn action(&mut self, font_system: &FontSystem, action: Action) {
|
||||
self.editor.action(font_system, action);
|
||||
}
|
||||
|
||||
/// Draw the editor
|
||||
#[cfg(feature = "swash")]
|
||||
fn draw<F>(&self, cache: &mut crate::SwashCache, _color: Color, mut f: F)
|
||||
where
|
||||
fn draw<F>(
|
||||
&self,
|
||||
font_system: &FontSystem,
|
||||
cache: &mut crate::SwashCache,
|
||||
_color: Color,
|
||||
mut f: F,
|
||||
) 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());
|
||||
self.editor.draw(cache, self.foreground_color(), f);
|
||||
self.editor
|
||||
.draw(font_system, cache, self.foreground_color(), f);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> BorrowedWithFontSystem<'b, SyntaxEditor<'a>> {
|
||||
/// Load text from a file, and also set syntax to the best option
|
||||
///
|
||||
/// ## Errors
|
||||
///
|
||||
/// 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) -> io::Result<()> {
|
||||
self.inner.load_text(self.font_system, path, attrs)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
107
src/edit/vi.rs
107
src/edit/vi.rs
|
|
@ -2,7 +2,10 @@ use alloc::string::String;
|
|||
use core::cmp;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::{Action, AttrsList, Buffer, Color, Cursor, Edit, SyntaxEditor};
|
||||
use crate::{
|
||||
Action, AttrsList, BorrowedWithFontSystem, Buffer, Color, Cursor, Edit, FontSystem,
|
||||
SyntaxEditor,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum Mode {
|
||||
|
|
@ -26,14 +29,14 @@ 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>>(
|
||||
pub(crate) fn load_text<P: AsRef<std::path::Path>>(
|
||||
&mut self,
|
||||
font_system: &FontSystem,
|
||||
path: P,
|
||||
attrs: crate::Attrs<'a>,
|
||||
attrs: crate::Attrs,
|
||||
) -> std::io::Result<()> {
|
||||
self.editor.load_text(path, attrs)
|
||||
self.editor.load_text(font_system, path, attrs)
|
||||
}
|
||||
|
||||
/// Get the default background color
|
||||
|
|
@ -47,12 +50,12 @@ impl<'a> ViEditor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Edit<'a> for ViEditor<'a> {
|
||||
fn buffer(&self) -> &Buffer<'a> {
|
||||
impl<'a> Edit for ViEditor<'a> {
|
||||
fn buffer(&self) -> &Buffer {
|
||||
self.editor.buffer()
|
||||
}
|
||||
|
||||
fn buffer_mut(&mut self) -> &mut Buffer<'a> {
|
||||
fn buffer_mut(&mut self) -> &mut Buffer {
|
||||
self.editor.buffer_mut()
|
||||
}
|
||||
|
||||
|
|
@ -68,8 +71,8 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
self.editor.set_select_opt(select_opt);
|
||||
}
|
||||
|
||||
fn shape_as_needed(&mut self) {
|
||||
self.editor.shape_as_needed()
|
||||
fn shape_as_needed(&mut self, font_system: &FontSystem) {
|
||||
self.editor.shape_as_needed(font_system);
|
||||
}
|
||||
|
||||
fn copy_selection(&mut self) -> Option<String> {
|
||||
|
|
@ -84,7 +87,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
self.editor.insert_string(data, attrs_list);
|
||||
}
|
||||
|
||||
fn action(&mut self, action: Action) {
|
||||
fn action(&mut self, font_system: &FontSystem, action: Action) {
|
||||
let old_mode = self.mode;
|
||||
|
||||
match self.mode {
|
||||
|
|
@ -92,18 +95,18 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
Action::Insert(c) => match c {
|
||||
// Enter insert mode after cursor
|
||||
'a' => {
|
||||
self.editor.action(Action::Right);
|
||||
self.editor.action(font_system, Action::Right);
|
||||
self.mode = Mode::Insert;
|
||||
}
|
||||
// Enter insert mode at end of line
|
||||
'A' => {
|
||||
self.editor.action(Action::End);
|
||||
self.editor.action(font_system, Action::End);
|
||||
self.mode = Mode::Insert;
|
||||
}
|
||||
// Change mode
|
||||
'c' => {
|
||||
if self.editor.select_opt().is_some() {
|
||||
self.editor.action(Action::Delete);
|
||||
self.editor.action(font_system, Action::Delete);
|
||||
self.mode = Mode::Insert;
|
||||
} else {
|
||||
//TODO: change to next cursor movement
|
||||
|
|
@ -112,7 +115,7 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
// Delete mode
|
||||
'd' => {
|
||||
if self.editor.select_opt().is_some() {
|
||||
self.editor.action(Action::Delete);
|
||||
self.editor.action(font_system, Action::Delete);
|
||||
} else {
|
||||
//TODO: delete to next cursor movement
|
||||
}
|
||||
|
|
@ -124,33 +127,33 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
// Enter insert mode at start of line
|
||||
'I' => {
|
||||
//TODO: soft home, skip whitespace
|
||||
self.editor.action(Action::Home);
|
||||
self.editor.action(font_system, Action::Home);
|
||||
self.mode = Mode::Insert;
|
||||
}
|
||||
// Create line after and enter insert mode
|
||||
'o' => {
|
||||
self.editor.action(Action::End);
|
||||
self.editor.action(Action::Enter);
|
||||
self.editor.action(font_system, Action::End);
|
||||
self.editor.action(font_system, Action::Enter);
|
||||
self.mode = Mode::Insert;
|
||||
}
|
||||
// Create line before and enter insert mode
|
||||
'O' => {
|
||||
self.editor.action(Action::Home);
|
||||
self.editor.action(Action::Enter);
|
||||
self.editor.shape_as_needed(); // TODO: do not require this?
|
||||
self.editor.action(Action::Up);
|
||||
self.editor.action(font_system, Action::Home);
|
||||
self.editor.action(font_system, Action::Enter);
|
||||
self.editor.shape_as_needed(font_system); // TODO: do not require this?
|
||||
self.editor.action(font_system, Action::Up);
|
||||
self.mode = Mode::Insert;
|
||||
}
|
||||
// Left
|
||||
'h' => self.editor.action(Action::Left),
|
||||
'h' => self.editor.action(font_system, Action::Left),
|
||||
// Top of screen
|
||||
//TODO: 'H' => self.editor.action(Action::ScreenHigh),
|
||||
// Down
|
||||
'j' => self.editor.action(Action::Down),
|
||||
'j' => self.editor.action(font_system, Action::Down),
|
||||
// Up
|
||||
'k' => self.editor.action(Action::Up),
|
||||
'k' => self.editor.action(font_system, Action::Up),
|
||||
// Right
|
||||
'l' => self.editor.action(Action::Right),
|
||||
'l' => self.editor.action(font_system, Action::Right),
|
||||
// Bottom of screen
|
||||
//TODO: 'L' => self.editor.action(Action::ScreenLow),
|
||||
// Middle of screen
|
||||
|
|
@ -168,23 +171,23 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
if self.editor.select_opt().is_some() {
|
||||
self.editor.set_select_opt(None);
|
||||
} else {
|
||||
self.editor.action(Action::Home);
|
||||
self.editor.action(font_system, Action::Home);
|
||||
self.editor.set_select_opt(Some(self.editor.cursor()));
|
||||
//TODO: set cursor_x_opt to max
|
||||
self.editor.action(Action::End);
|
||||
self.editor.action(font_system, Action::End);
|
||||
}
|
||||
}
|
||||
// Remove character at cursor
|
||||
'x' => self.editor.action(Action::Delete),
|
||||
'x' => self.editor.action(font_system, Action::Delete),
|
||||
// Remove character before cursor
|
||||
'X' => self.editor.action(Action::Backspace),
|
||||
'X' => self.editor.action(font_system, Action::Backspace),
|
||||
// Go to start of line
|
||||
'0' => self.editor.action(Action::Home),
|
||||
'0' => self.editor.action(font_system, Action::Home),
|
||||
// Go to end of line
|
||||
'$' => self.editor.action(Action::End),
|
||||
'$' => self.editor.action(font_system, Action::End),
|
||||
// Go to start of line after whitespace
|
||||
//TODO: implement this
|
||||
'^' => self.editor.action(Action::Home),
|
||||
'^' => self.editor.action(font_system, Action::Home),
|
||||
// Enter command mode
|
||||
':' => {
|
||||
self.mode = Mode::Command;
|
||||
|
|
@ -199,18 +202,18 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
}
|
||||
_ => (),
|
||||
},
|
||||
_ => self.editor.action(action),
|
||||
_ => self.editor.action(font_system, action),
|
||||
},
|
||||
Mode::Insert => match action {
|
||||
Action::Escape => {
|
||||
let cursor = self.cursor();
|
||||
let layout_cursor = self.buffer().layout_cursor(&cursor);
|
||||
if layout_cursor.glyph > 0 {
|
||||
self.editor.action(Action::Left);
|
||||
self.editor.action(font_system, Action::Left);
|
||||
}
|
||||
self.mode = Mode::Normal;
|
||||
}
|
||||
_ => self.editor.action(action),
|
||||
_ => self.editor.action(font_system, action),
|
||||
},
|
||||
_ => {
|
||||
//TODO: other modes
|
||||
|
|
@ -224,8 +227,13 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
}
|
||||
|
||||
#[cfg(feature = "swash")]
|
||||
fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, mut f: F)
|
||||
where
|
||||
fn draw<F>(
|
||||
&self,
|
||||
font_system: &FontSystem,
|
||||
cache: &mut crate::SwashCache,
|
||||
color: Color,
|
||||
mut f: F,
|
||||
) where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
let font_size = self.buffer().metrics().font_size;
|
||||
|
|
@ -421,15 +429,22 @@ impl<'a> Edit<'a> for ViEditor<'a> {
|
|||
None => color,
|
||||
};
|
||||
|
||||
cache.with_pixels(
|
||||
self.buffer().font_system(),
|
||||
cache_key,
|
||||
glyph_color,
|
||||
|x, y, color| {
|
||||
f(x_int + x, line_y as i32 + y_int + y, 1, 1, color);
|
||||
},
|
||||
);
|
||||
cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| {
|
||||
f(x_int + x, line_y as i32 + y_int + y, 1, 1, color);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> BorrowedWithFontSystem<'b, 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,
|
||||
) -> std::io::Result<()> {
|
||||
self.inner.load_text(self.font_system, path, attrs)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue