Add move down
This commit is contained in:
parent
8bda7f99e4
commit
efcdcac1fb
@ -13,9 +13,7 @@ pub fn move_caret_right(file_editor: &mut FileEditor) {
|
||||
let pos = file_editor.caret().position();
|
||||
let d = c.dest().clone();
|
||||
let p = pos.moved(1, 0, 0);
|
||||
file_editor
|
||||
.caret_mut()
|
||||
.move_caret(p, Point::new(d.x(), d.y()));
|
||||
file_editor.caret_mut().move_caret(p, d.top_left());
|
||||
}
|
||||
|
||||
pub fn move_caret_left(file_editor: &mut FileEditor) {
|
||||
@ -34,9 +32,52 @@ pub fn move_caret_left(file_editor: &mut FileEditor) {
|
||||
let pos = file_editor.caret().position();
|
||||
let character_destination = text_character.dest().clone();
|
||||
let p = pos.moved(-1, 0, 0);
|
||||
file_editor
|
||||
.caret_mut()
|
||||
.move_caret(p, character_destination.top_left());
|
||||
}
|
||||
|
||||
pub fn move_caret_down(file_editor: &mut FileEditor) {
|
||||
let file: &EditorFile = match file_editor.file() {
|
||||
None => return,
|
||||
Some(f) => f,
|
||||
};
|
||||
if file_editor.caret().text_position() == 0 {
|
||||
return;
|
||||
}
|
||||
let current_line_number = file_editor.caret().line_number();
|
||||
let mut next_line_position = 0;
|
||||
let mut desired_line_position = 0;
|
||||
let mut text_character: Option<&TextCharacter> = None;
|
||||
for c in file.iter_char() {
|
||||
match c.line() {
|
||||
line if c.position() < file_editor.caret().text_position()
|
||||
&& current_line_number == line =>
|
||||
{
|
||||
desired_line_position += 1;
|
||||
}
|
||||
line if line == current_line_number + 1 => {
|
||||
text_character = Some(c);
|
||||
if next_line_position == desired_line_position {
|
||||
break;
|
||||
}
|
||||
next_line_position += 1;
|
||||
}
|
||||
line if line == current_line_number + 2 => {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let text_character: &TextCharacter = match text_character {
|
||||
Some(text_character) => text_character,
|
||||
None => return, // EOF
|
||||
};
|
||||
let character_destination = text_character.dest().clone();
|
||||
let pos = text_character.position().clone();
|
||||
file_editor.caret_mut().move_caret(
|
||||
p,
|
||||
Point::new(character_destination.x(), character_destination.y()),
|
||||
CaretPosition::new(pos, current_line_number + 1, next_line_position),
|
||||
character_destination.top_left(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::app::*;
|
||||
use crate::renderer::renderer::Renderer;
|
||||
use crate::ui::*;
|
||||
use sdl2::rect::{Point, Rect};
|
||||
use sdl2::rect::Point;
|
||||
use std::sync::*;
|
||||
|
||||
pub fn current_file_path(file_editor: &mut FileEditor) -> String {
|
||||
@ -142,6 +142,7 @@ mod tests {
|
||||
use crate::renderer::managers::FontDetails;
|
||||
use crate::renderer::managers::TextDetails;
|
||||
use crate::tests::support;
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::render::Texture;
|
||||
use sdl2::ttf::Font;
|
||||
use std::rc::Rc;
|
||||
|
@ -24,7 +24,7 @@ pub mod ui;
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn init_logger(directories: &Directories) {
|
||||
use simplelog::SharedLogger;
|
||||
// use simplelog::SharedLogger;
|
||||
|
||||
let mut log_file_path = directories.log_dir.clone();
|
||||
log_file_path.push("rider.log");
|
||||
|
@ -111,7 +111,7 @@ impl<'l> Renderer for CanvasRenderer<'l> {
|
||||
details: &mut TextDetails,
|
||||
font_details: FontDetails,
|
||||
) -> Result<Rc<Texture>, String> {
|
||||
use crate::renderer::managers::TextTextureManager;
|
||||
use crate::renderer::managers::*;
|
||||
let font = self
|
||||
.font_manager()
|
||||
.load(&font_details)
|
||||
|
@ -73,6 +73,10 @@ impl EditorFile {
|
||||
section.update_positions(&mut current);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_char(&self) -> EditorFileIterator {
|
||||
EditorFileIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl TextCollection for EditorFile {
|
||||
@ -208,12 +212,94 @@ impl RenderBox for EditorFile {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EditorFileIterator<'a> {
|
||||
current_section: usize,
|
||||
current_token: usize,
|
||||
current_character: usize,
|
||||
file: &'a EditorFile,
|
||||
}
|
||||
|
||||
impl<'a> EditorFileIterator<'a> {
|
||||
pub fn new(file: &'a EditorFile) -> Self {
|
||||
Self {
|
||||
file,
|
||||
current_section: 0,
|
||||
current_token: 0,
|
||||
current_character: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_section(&self) -> Option<&'a EditorFileSection> {
|
||||
self.file.sections().get(self.current_section)
|
||||
}
|
||||
|
||||
fn get_token(&mut self, section: &'a EditorFileSection) -> Option<&'a EditorFileToken> {
|
||||
section.tokens().get(self.current_token).or_else(|| {
|
||||
self.current_section += 1;
|
||||
self.current_token = 0;
|
||||
self.current_character = 0;
|
||||
self.get_token(self.get_section()?)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_character(&mut self, token: &'a EditorFileToken) -> Option<&'a TextCharacter> {
|
||||
token
|
||||
.characters()
|
||||
.get(self.current_character)
|
||||
.or_else(|| {
|
||||
self.current_character = 0;
|
||||
self.current_token += 1;
|
||||
let token = self.get_token(self.get_section()?)?;
|
||||
self.get_character(token)
|
||||
})
|
||||
.and_then(|c| {
|
||||
self.current_character += 1;
|
||||
Some(c)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for EditorFileIterator<'a> {
|
||||
type Item = &'a TextCharacter;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let token = self.get_token(self.get_section()?)?;
|
||||
self.get_character(token)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::support;
|
||||
use crate::tests::support::SimpleRendererMock;
|
||||
use crate::ui::*;
|
||||
use sdl2::rect::{Point, Rect};
|
||||
|
||||
//##################################################
|
||||
// iterator
|
||||
//##################################################
|
||||
|
||||
#[test]
|
||||
fn assert_simple_iterations() {
|
||||
let config = support::build_config();
|
||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
||||
let mut file =
|
||||
EditorFile::new("./foo.txt".to_owned(), "a b c d".to_owned(), config.clone());
|
||||
file.prepare_ui(&mut renderer);
|
||||
for (index, c) in file.iter_char().enumerate() {
|
||||
match index {
|
||||
0 => assert_eq!(c.text_character(), 'a'),
|
||||
1 => assert_eq!(c.text_character(), ' '),
|
||||
2 => assert_eq!(c.text_character(), 'b'),
|
||||
3 => assert_eq!(c.text_character(), ' '),
|
||||
4 => assert_eq!(c.text_character(), 'c'),
|
||||
5 => assert_eq!(c.text_character(), ' '),
|
||||
6 => assert_eq!(c.text_character(), 'd'),
|
||||
_ => assert_eq!("must have 7 entries", "have more than 7 entries"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//##################################################
|
||||
// path
|
||||
//##################################################
|
||||
|
@ -79,6 +79,14 @@ impl EditorFileSection {
|
||||
token.prepare_ui(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_char(&self) -> EditorFileSectionIterator {
|
||||
EditorFileSectionIterator::new(self)
|
||||
}
|
||||
|
||||
pub fn tokens(&self) -> &Vec<EditorFileToken> {
|
||||
&self.tokens
|
||||
}
|
||||
}
|
||||
|
||||
impl TextWidget for EditorFileSection {
|
||||
@ -188,16 +196,55 @@ impl ClickHandler for EditorFileSection {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EditorFileSectionIterator<'a> {
|
||||
section: &'a EditorFileSection,
|
||||
current_token: usize,
|
||||
current_character: usize,
|
||||
}
|
||||
|
||||
impl<'a> EditorFileSectionIterator<'a> {
|
||||
pub fn new(section: &'a EditorFileSection) -> Self {
|
||||
Self {
|
||||
section,
|
||||
current_token: 0,
|
||||
current_character: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_token(&self) -> Option<&'a EditorFileToken> {
|
||||
self.section.tokens.get(self.current_token)
|
||||
}
|
||||
|
||||
fn get_character(&mut self, token: &'a EditorFileToken) -> Option<&'a TextCharacter> {
|
||||
token
|
||||
.characters()
|
||||
.get(self.current_character)
|
||||
.or_else(|| {
|
||||
self.current_character = 0;
|
||||
self.current_token += 1;
|
||||
self.get_character(self.get_token()?)
|
||||
})
|
||||
.and_then(|c| {
|
||||
self.current_character += 1;
|
||||
Some(c)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::iter::Iterator for EditorFileSectionIterator<'a> {
|
||||
type Item = &'a TextCharacter;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.get_character(self.get_token()?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::tests::support::build_config;
|
||||
use crate::tests::support::{build_config, SimpleRendererMock};
|
||||
|
||||
impl EditorFileSection {
|
||||
pub fn tokens(&self) -> Vec<EditorFileToken> {
|
||||
self.tokens.clone()
|
||||
}
|
||||
|
||||
pub fn tokens_count(&self) -> usize {
|
||||
self.tokens.len()
|
||||
}
|
||||
@ -218,4 +265,47 @@ mod tests {
|
||||
assert_eq!(widget.language(), Language::Rust);
|
||||
assert_eq!(widget.tokens_count(), 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assert_simple_char_iteration() {
|
||||
let config = build_config();
|
||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
||||
let mut section = EditorFileSection::new("a b c d".to_owned(), ".txt".to_owned(), config);
|
||||
section.prepare_ui(&mut renderer);
|
||||
for (index, c) in section.iter_char().enumerate() {
|
||||
match index {
|
||||
0 => assert_eq!(c.text_character(), 'a'),
|
||||
1 => assert_eq!(c.text_character(), ' '),
|
||||
2 => assert_eq!(c.text_character(), 'b'),
|
||||
3 => assert_eq!(c.text_character(), ' '),
|
||||
4 => assert_eq!(c.text_character(), 'c'),
|
||||
5 => assert_eq!(c.text_character(), ' '),
|
||||
6 => assert_eq!(c.text_character(), 'd'),
|
||||
_ => assert_eq!("must have 7 entries", "have more than 7 entries"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assert_complex_char_iteration() {
|
||||
let config = build_config();
|
||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
||||
let mut section = EditorFileSection::new("let a = 1".to_owned(), ".rs".to_owned(), config);
|
||||
section.prepare_ui(&mut renderer);
|
||||
assert_eq!(section.tokens.len(), 7);
|
||||
for (index, c) in section.iter_char().enumerate() {
|
||||
match index {
|
||||
0 => assert_eq!(c.text_character(), 'l'),
|
||||
1 => assert_eq!(c.text_character(), 'e'),
|
||||
2 => assert_eq!(c.text_character(), 't'),
|
||||
3 => assert_eq!(c.text_character(), ' '),
|
||||
4 => assert_eq!(c.text_character(), 'a'),
|
||||
5 => assert_eq!(c.text_character(), ' '),
|
||||
6 => assert_eq!(c.text_character(), '='),
|
||||
7 => assert_eq!(c.text_character(), ' '),
|
||||
8 => assert_eq!(c.text_character(), '1'),
|
||||
_ => assert_eq!("must have 9 entries", "have more than 9 entries"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ impl EditorFileToken {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn characters(&self) -> &Vec<TextCharacter> {
|
||||
&self.characters
|
||||
}
|
||||
|
||||
fn token_to_color(&self, config: &Arc<RwLock<Config>>) -> Color {
|
||||
let config = config.read().unwrap();
|
||||
let ch = config.theme().code_highlighting();
|
||||
@ -54,6 +58,10 @@ impl EditorFileToken {
|
||||
&TokenType::Separator { .. } => ch.separator().color().into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_char(&self) -> EditorFileTokenIterator {
|
||||
EditorFileTokenIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl TextWidget for EditorFileToken {
|
||||
@ -196,6 +204,32 @@ impl ClickHandler for EditorFileToken {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EditorFileTokenIterator<'a> {
|
||||
editor_file_token: &'a EditorFileToken,
|
||||
current_character: usize,
|
||||
}
|
||||
|
||||
impl<'a> EditorFileTokenIterator<'a> {
|
||||
pub fn new(editor_file_token: &'a EditorFileToken) -> Self {
|
||||
Self {
|
||||
editor_file_token,
|
||||
current_character: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::iter::Iterator for EditorFileTokenIterator<'a> {
|
||||
type Item = &'a TextCharacter;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.current_character += 1;
|
||||
self.editor_file_token
|
||||
.characters
|
||||
.get(self.current_character)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -243,11 +277,6 @@ mod tests {
|
||||
unimplemented!("load_font")
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn load_image(&mut self, _path: String) -> Result<Rc<Texture>, String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn load_text_tex(
|
||||
&mut self,
|
||||
_details: &mut TextDetails,
|
||||
@ -265,6 +294,11 @@ mod tests {
|
||||
// }, Ok)
|
||||
Err("".to_owned())
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn load_image(&mut self, _path: String) -> Result<Rc<Texture>, String> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> CharacterSizeManager for RendererMock<'l> {
|
||||
@ -279,6 +313,28 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
//##################################################
|
||||
// iterator
|
||||
//##################################################
|
||||
|
||||
#[test]
|
||||
fn assert_iterator() {
|
||||
let config = build_config();
|
||||
let token_type = TokenType::String {
|
||||
token: Token::new("abcd".to_owned(), 0, 0, 0, 3),
|
||||
};
|
||||
let token = EditorFileToken::new(&token_type, true, config.clone());
|
||||
for (i, c) in token.iter_char().enumerate() {
|
||||
match i {
|
||||
0 => assert_eq!(c.text_character(), 'a'),
|
||||
1 => assert_eq!(c.text_character(), 'b'),
|
||||
2 => assert_eq!(c.text_character(), 'c'),
|
||||
3 => assert_eq!(c.text_character(), 'd'),
|
||||
_ => assert_eq!("must have 4 characters", "have more than 4 characters"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//##################################################
|
||||
// token_to_color
|
||||
//##################################################
|
||||
|
@ -221,7 +221,7 @@ impl CaretAccess for FileEditor {
|
||||
MoveDirection::Left => caret_manager::move_caret_left(self),
|
||||
MoveDirection::Right => caret_manager::move_caret_right(self),
|
||||
MoveDirection::Up => {}
|
||||
MoveDirection::Down => {}
|
||||
MoveDirection::Down => caret_manager::move_caret_down(self),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user