Implement scroll
This commit is contained in:
parent
0c64c43278
commit
b3c2744e2d
3
Makefile
3
Makefile
@ -1,2 +1,5 @@
|
|||||||
test:
|
test:
|
||||||
RUST_BACKTRACE=1 cargo test
|
RUST_BACKTRACE=1 cargo test
|
||||||
|
|
||||||
|
run:
|
||||||
|
RUST_BACKTRACE=1 cargo run
|
||||||
|
52
src/nvim.rs
52
src/nvim.rs
@ -23,6 +23,10 @@ pub trait RedrawEvents {
|
|||||||
fn on_highlight_set(&mut self, attrs: &HashMap<String, Value>);
|
fn on_highlight_set(&mut self, attrs: &HashMap<String, Value>);
|
||||||
|
|
||||||
fn on_eol_clear(&mut self);
|
fn on_eol_clear(&mut self);
|
||||||
|
|
||||||
|
fn on_set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64);
|
||||||
|
|
||||||
|
fn on_scroll(&mut self, count: i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! try_str {
|
macro_rules! try_str {
|
||||||
@ -33,9 +37,17 @@ macro_rules! try_str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! try_int {
|
macro_rules! try_int {
|
||||||
|
($expr:expr) => (match $expr {
|
||||||
|
Value::Integer(Integer::U64(val)) => val as i64,
|
||||||
|
Value::Integer(Integer::I64(val)) => val,
|
||||||
|
_ => return Err("Can't convert argument to int".to_owned())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! try_uint {
|
||||||
($exp:expr) => (match $exp {
|
($exp:expr) => (match $exp {
|
||||||
Value::Integer(Integer::U64(val)) => val,
|
Value::Integer(Integer::U64(val)) => val,
|
||||||
_ => return Err("Can't convert argument to int".to_owned())
|
_ => return Err("Can't convert argument to u64".to_owned())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +105,7 @@ fn call(method: &str, args: Vec<Value>) {
|
|||||||
match method {
|
match method {
|
||||||
"cursor_goto" => {
|
"cursor_goto" => {
|
||||||
safe_call(move |ui| {
|
safe_call(move |ui| {
|
||||||
ui.on_cursor_goto(try_int!(args[0]), try_int!(args[1]));
|
ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1]));
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -111,19 +123,29 @@ fn call(method: &str, args: Vec<Value>) {
|
|||||||
}
|
}
|
||||||
"resize" => {
|
"resize" => {
|
||||||
safe_call(move |ui| {
|
safe_call(move |ui| {
|
||||||
ui.on_resize(try_int!(args[0]), try_int!(args[1]));
|
ui.on_resize(try_uint!(args[0]), try_uint!(args[1]));
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"highlight_set" => {
|
"highlight_set" => {
|
||||||
safe_call(move |ui| {
|
safe_call(move |ui| {
|
||||||
if let Value::Map(ref attrs) = args[0] {
|
if let Value::Map(ref attrs) = args[0] {
|
||||||
let attrs_map: HashMap<String, Value> = attrs.iter().map(|v| {
|
let attrs_map: HashMap<String, Value> = attrs.iter()
|
||||||
match v {
|
.map(|v| {
|
||||||
&(Value::String(ref key), ref value) => (key.clone(), value.clone()),
|
match v {
|
||||||
_ => panic!("attribute key must be string"),
|
&(Value::String(ref key),
|
||||||
}
|
ref value) => {
|
||||||
}).collect();
|
(key.clone(),
|
||||||
|
value.clone())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("attribute \
|
||||||
|
key must be \
|
||||||
|
string")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
ui.on_highlight_set(&attrs_map);
|
ui.on_highlight_set(&attrs_map);
|
||||||
} else {
|
} else {
|
||||||
panic!("Supports only map value as argument");
|
panic!("Supports only map value as argument");
|
||||||
@ -137,6 +159,18 @@ fn call(method: &str, args: Vec<Value>) {
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
"set_scroll_region" => {
|
||||||
|
safe_call(move |ui| {
|
||||||
|
ui.on_set_scroll_region(try_uint!(args[0]), try_uint!(args[1]), try_uint!(args[2]), try_uint!(args[3]));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"scroll" => {
|
||||||
|
safe_call(move |ui| {
|
||||||
|
ui.on_scroll(try_int!(args[0]));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
_ => println!("Event {}({:?})", method, args),
|
_ => println!("Event {}({:?})", method, args),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,14 @@ impl RedrawEvents for Ui {
|
|||||||
self.drawing_area.queue_draw();
|
self.drawing_area.queue_draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64) {
|
||||||
|
self.model.set_scroll_region(top, bot, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_scroll(&mut self, count: i64) {
|
||||||
|
self.model.scroll(count);
|
||||||
|
}
|
||||||
|
|
||||||
fn on_highlight_set(&mut self, attrs: &HashMap<String, Value>) {
|
fn on_highlight_set(&mut self, attrs: &HashMap<String, Value>) {
|
||||||
let mut model_attrs = Attrs::new();
|
let mut model_attrs = Attrs::new();
|
||||||
if let Some(&Value::Integer(Integer::U64(fg))) = attrs.get("foreground") {
|
if let Some(&Value::Integer(Integer::U64(fg))) = attrs.get("foreground") {
|
||||||
|
@ -31,6 +31,7 @@ impl Attrs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Cell {
|
pub struct Cell {
|
||||||
pub ch: char,
|
pub ch: char,
|
||||||
pub attrs: Attrs,
|
pub attrs: Attrs,
|
||||||
@ -56,6 +57,10 @@ pub struct UiModel {
|
|||||||
cur_row: usize,
|
cur_row: usize,
|
||||||
cur_col: usize,
|
cur_col: usize,
|
||||||
model: Vec<Vec<Cell>>,
|
model: Vec<Vec<Cell>>,
|
||||||
|
top: usize,
|
||||||
|
bot: usize,
|
||||||
|
left: usize,
|
||||||
|
right: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiModel {
|
impl UiModel {
|
||||||
@ -78,6 +83,10 @@ impl UiModel {
|
|||||||
cur_row: 0,
|
cur_row: 0,
|
||||||
cur_col: 0,
|
cur_col: 0,
|
||||||
model: model,
|
model: model,
|
||||||
|
top: 0,
|
||||||
|
bot: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,12 +106,44 @@ impl UiModel {
|
|||||||
self.cur_col += 1;
|
self.cur_col += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64) {
|
||||||
for row in 0..self.rows {
|
self.top = top as usize;
|
||||||
for col in 0..self.columns {
|
self.bot = bot as usize;
|
||||||
self.model[row][col].clear();
|
self.left = left as usize;
|
||||||
|
self.right = right as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_row(&mut self, row: usize, offset: i64, left: usize, right: usize) {
|
||||||
|
for col in left..right + 1 {
|
||||||
|
let from_row = (row as i64 + offset) as usize;
|
||||||
|
let from_cell = self.model[from_row][col].clone();
|
||||||
|
self.model[row][col] = from_cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scroll(&mut self, count: i64) {
|
||||||
|
let (top, bot, left, right) = (self.top as i64, self.bot as i64, self.left, self.right);
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
for row in top as usize..(bot - count + 1) as usize {
|
||||||
|
self.copy_row(row, count, left, right);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for row in ((top - count) as usize..(bot + 1) as usize).rev() {
|
||||||
|
self.copy_row(row, count, left, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
self.clear_region((bot - count + 1) as usize, bot as usize, left, right);
|
||||||
|
} else {
|
||||||
|
self.clear_region(top as usize, (top - count - 1) as usize, left, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
let (rows, columns) = (self.rows, self.columns);
|
||||||
|
self.clear_region(0, rows - 1, 0, columns - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eol_clear(&mut self) {
|
pub fn eol_clear(&mut self) {
|
||||||
@ -111,9 +152,9 @@ impl UiModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clear_region(&mut self, top: usize, bot: usize, left: usize, right: usize) {
|
fn clear_region(&mut self, top: usize, bot: usize, left: usize, right: usize) {
|
||||||
for row in top..bot + 1 {
|
for row in &mut self.model[top..bot + 1] {
|
||||||
for col in left..right + 1 {
|
for cell in &mut row[left..right + 1] {
|
||||||
self.model[row][col].clear();
|
cell.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user