Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加撤销树结构以及一些接口 #18

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/config/lastline_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl LastLineCommand {
}
}

const fn is_split_char(x: char) -> bool {
pub const fn is_split_char(x: char) -> bool {
x == ',' || x == ';' || x == ':' || x == '/' || x.is_ascii_whitespace()
}

Expand Down
30 changes: 30 additions & 0 deletions src/utils/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
atomic::{AtomicUsize, Ordering},
RwLock,
},
usize,
};

use bitflags::bitflags;
Expand Down Expand Up @@ -145,6 +146,18 @@ impl EditBuffer {
Some(ret)
}

pub fn get_linesize_absoluted(&self, line: u16) -> u16 {
let buf = self.buf.read().unwrap();
let line = buf.get(line as usize);
if line.is_none() {
return 0;
}

let line = line.unwrap();

line.data.len() as u16
}

pub fn get_linesize(&self, line: u16) -> u16 {
let buf = self.buf.read().unwrap();
let line = buf.get(self.offset.load(Ordering::SeqCst) + line as usize);
Expand Down Expand Up @@ -178,6 +191,23 @@ impl EditBuffer {
line.unwrap().data.drain(x..x + n);
}

pub fn remove_str_abs(&self, x: u16, y: u16, n: usize) {
let mut buf = self.buf.write().unwrap();
let line = buf.get_mut(y as usize);
if line.is_none() {
return;
}
let x = x as usize;
match n {
usize::MAX => {
line.unwrap().data.drain(x..);
}
n => {
line.unwrap().data.drain(x..x + n);
}
}
}

/// 获取一份对应行的拷贝
pub fn get_line(&self, line: u16) -> LineBuffer {
let buf = self.buf.read().unwrap();
Expand Down
1 change: 1 addition & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ pub mod style;
pub mod term_io;
pub mod terminal;
pub mod ui;
mod undotree;
7 changes: 7 additions & 0 deletions src/utils/ui/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ pub trait KeyEventCallback {
ui: &mut MutexGuard<UiCore>,
data: &[u8],
) -> io::Result<WarpUiCallBackType>;

// 测试用,有需要的话可以删除此函数
// fn t(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
// ui.delete_range((4,3), (6,9))?;
// // ui.goto_line("15,8")?;
// Ok(WarpUiCallBackType::None)
// }
}

#[derive(Debug, PartialEq)]
Expand Down
6 changes: 6 additions & 0 deletions src/utils/ui/mode/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,12 @@ impl KeyEventCallback for Command {
return Ok(WarpUiCallBackType::None);
}

// 测试用,有需要的话可以删除此函数
// b"t" => {
// self.t(ui)?;
// Ok(WarpUiCallBackType::None)
// }

_ => {
return Ok(WarpUiCallBackType::None);
}
Expand Down
143 changes: 142 additions & 1 deletion src/utils/ui/uicore.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
io,
sync::{atomic::AtomicU16, Arc, Mutex, MutexGuard, Once, RwLock, Weak},
usize,
};

use crossterm::{
Expand All @@ -10,7 +11,7 @@ use crossterm::{
use lazy_static::lazy_static;

use crate::{
config::appconfig::AppSetting,
config::{appconfig::AppSetting, lastline_cmd::LastLineCommand},
utils::{
buffer::EditBuffer, cursor::CursorCrtl, style::StyleManager, terminal::TermManager,
ui::InfoLevel,
Expand Down Expand Up @@ -231,6 +232,146 @@ impl UiCore {

Ok(())
}

/// 删除指定坐标里的内容
/// 可以多行,下标从1开始,最开始的字符会被删除,选中内容的最后一个字符不会被删除
pub fn delete_range(&mut self, start_pos: (u16, u16), end_pos: (u16, u16)) -> io::Result<()> {
let content_winsize = *CONTENT_WINSIZE.read().unwrap();
let content_line_max = content_winsize.rows;

if start_pos.0 > end_pos.0 || start_pos.1 > end_pos.1 {
APP_INFO.lock().unwrap().info =
"Useage: {delete}|{d} {start_row}{start_col} {end_row}{end_col}".to_string();
return Ok(());
}

let (start_y, mut start_x) = start_pos;
let (end_y, mut end_x) = end_pos;

let buffer_line_max = self.buffer.line_count() as u16;
let mut start_y = start_y.min(buffer_line_max - 1);
let mut end_y = end_y.min(buffer_line_max - 1);
let start_y_line_count = self.buffer.get_linesize_absoluted(start_y);
let end_y_line_count = self.buffer.get_linesize_absoluted(end_y);
start_x = start_x.min(start_y_line_count);
end_x = end_x.min(end_y_line_count - 1);
// let end_y_line_count = self.buffer.get_linesize_absoluted(end_y);

// 以便后面能够得到正确的索引
if start_y == 0 {
start_y += 1;
}
if start_x == 0 {
start_x += 1;
}
if end_x == 0 {
end_x += 1;
}
if end_y == 0 {
end_y += 1;
}

start_x -= 1;
start_y -= 1;
end_y -= 1;
end_x -= 1;

if start_y == end_y {
self.buffer
.remove_str_abs(start_x, start_y, (end_x - start_x + 1) as usize);
} else {
self.buffer.remove_str_abs(start_x, start_y, usize::MAX);
self.buffer.remove_str_abs(0, end_y, end_x as usize);
if start_y.max(end_y) - start_y.min(end_y) > 1 {
self.buffer
.delete_lines((start_y + 1) as usize, (end_y - 1) as usize);
}
}
if self.buffer.offset() > self.buffer.line_count() {
self.buffer.set_offset(self.buffer.line_count());
}

// let y = self.cursor.y();
self.goto_line(&format!("{}", start_y + 1))?;

self.cursor.store_pos();
self.cursor.set_prefix_mode(true);
self.cursor.restore_pos().unwrap();

let pos = self.cursor.store_tmp_pos();
// self.render_content(y, (content_winsize.rows - y) as usize - 1)
// .unwrap();
self.render_content(0, content_line_max as usize).unwrap();

self.cursor.restore_tmp_pos(pos)?;

self.cursor.highlight(Some(self.cursor.y() - 1))?;
Ok(())
}

/// 跳转到指定坐标(下标从1开始)
pub fn goto_line(&mut self, args: &str) -> io::Result<()> {
if args.is_empty() {
let mut info = APP_INFO.lock().unwrap();
info.level = InfoLevel::Info;
info.info = "Useage: {goto}|{gt} {row}{' '|','|';'|':'|'/'}{col}".to_string();
return Ok(());
}
let (y, x) = {
let a = args
.split(|x| LastLineCommand::is_split_char(x))
.collect::<Vec<_>>();

if a.len() == 1 {
(u16::from_str_radix(a[0], 10), Ok(1))
} else {
(u16::from_str_radix(a[0], 10), u16::from_str_radix(a[1], 10))
}
};
if y.is_err() {
let mut info = APP_INFO.lock().unwrap();
info.level = InfoLevel::Info;
info.info = "Useage: goto {row}({' '|','|';'|':'|'/'}{col})".to_string();
}

let content_winsize = *CONTENT_WINSIZE.read().unwrap();
let content_line_max = content_winsize.rows;
let buf_line_max = self.buffer.line_count() as u16;
let mut y = y.unwrap().min(buf_line_max);
let mut x = x.unwrap_or(1).min(self.buffer.get_linesize_absoluted(y));

// 以便后面能够得到正确的索引
if y == 0 {
y += 1;
}
if x == 0 {
x += 1;
}

x -= 1;
y -= 1;

self.cursor.store_pos();
self.cursor.set_prefix_mode(true);
self.cursor.restore_pos().unwrap();

let lasty = self.cursor.y();
let y = self.buffer.goto_line(y as usize);
self.cursor.move_to(x, y).unwrap();

let pos = self.cursor.store_tmp_pos();
self.render_content(0, content_line_max as usize).unwrap();
self.cursor.restore_tmp_pos(pos).unwrap();

self.cursor.highlight(Some(lasty)).unwrap();

Ok(())
}

pub fn insert_str_with_newline(&mut self, _x: u16, _y: u16, _s: &str) -> io::Result<()> {

Ok(())
}
}

#[derive(Debug)]
Expand Down
Loading