From 797de26ec27d1ea91e144f9e677b759c9b22df39 Mon Sep 17 00:00:00 2001 From: daa84 Date: Fri, 17 Nov 2017 18:40:09 +0300 Subject: [PATCH] Add ext_cmd event processing Update event processing code --- Cargo.lock | 1 + Cargo.toml | 1 + src/main.rs | 1 + src/nvim/cmd_line.rs | 30 +++++++++++++++++++ src/nvim/handler.rs | 2 +- src/nvim/mod.rs | 37 ++++++++++++++--------- src/nvim/redraw_handler.rs | 56 ++++++++++++++++++++++++++--------- src/shell.rs | 60 +++++++++++++++----------------------- src/ui_model/cell.rs | 35 ++++++++++++++++++++++ 9 files changed, 158 insertions(+), 65 deletions(-) create mode 100644 src/nvim/cmd_line.rs diff --git a/Cargo.lock b/Cargo.lock index ea6948b..1cd681f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,7 @@ dependencies = [ "pangocairo 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rmpv 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 0db4b11..736920d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ phf = "0.7" log = "0.3" env_logger = "0.4" htmlescape = "0.3" +rmpv = "0.4" serde = "1.0" serde_derive = "1.0" diff --git a/src/main.rs b/src/main.rs index 6dcf074..8c1b907 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ extern crate phf; extern crate log; extern crate env_logger; extern crate htmlescape; +extern crate rmpv; extern crate serde; #[macro_use] diff --git a/src/nvim/cmd_line.rs b/src/nvim/cmd_line.rs new file mode 100644 index 0000000..5b539a1 --- /dev/null +++ b/src/nvim/cmd_line.rs @@ -0,0 +1,30 @@ +use ui_model; + +pub struct CmdLine { + content: Vec<(ui_model::Attrs, String)>, + pos: u64, + firstc: String, + prompt: String, + indent: u64, + level: u64, +} + +impl CmdLine { + pub fn new( + content: Vec<(ui_model::Attrs, String)>, + pos: u64, + firstc: String, + prompt: String, + indent: u64, + level: u64, + ) -> Self { + CmdLine { + content, + pos, + firstc, + prompt, + indent, + level, + } + } +} diff --git a/src/nvim/handler.rs b/src/nvim/handler.rs index 4128617..34e1c44 100644 --- a/src/nvim/handler.rs +++ b/src/nvim/handler.rs @@ -38,7 +38,7 @@ impl NvimHandler { _ => vec![], }; let call_reapint_mode = - redraw_handler::call(ui, &ev_name, &args)?; + redraw_handler::call(ui, &ev_name, args)?; repaint_mode = repaint_mode.join(call_reapint_mode); } } else { diff --git a/src/nvim/mod.rs b/src/nvim/mod.rs index 504f8fe..d7f477c 100644 --- a/src/nvim/mod.rs +++ b/src/nvim/mod.rs @@ -4,11 +4,13 @@ mod handler; mod mode_info; mod redraw_handler; mod repaint_mode; +mod cmd_line; pub use self::redraw_handler::{RedrawEvents, GuiApi}; pub use self::repaint_mode::RepaintMode; pub use self::client::{NeovimClient, NeovimClientAsync, NeovimRef}; pub use self::mode_info::{ModeInfo, CursorShape}; +pub use self::cmd_line::{CmdLine}; use std::error; use std::fmt; @@ -136,20 +138,28 @@ pub fn post_start_init( cols: u64, rows: u64, ) -> result::Result<(), NvimInitError> { - let mut opts = UiAttachOptions::new(); - opts.set_popupmenu_external(true); - opts.set_tabline_external(true); - nvim.borrow().unwrap().ui_attach(cols, rows, &opts).map_err( - NvimInitError::new_post_init, - )?; - nvim.borrow().unwrap().command("runtime! ginit.vim").map_err( - NvimInitError::new_post_init, - )?; + nvim.borrow() + .unwrap() + .ui_attach( + cols, + rows, + UiAttachOptions::new() + .set_popupmenu_external(true) + .set_tabline_external(true) + .set_cmdline_external(true), + ) + .map_err(NvimInitError::new_post_init)?; + + nvim.borrow() + .unwrap() + .command("runtime! ginit.vim") + .map_err(NvimInitError::new_post_init)?; if let Some(path) = open_path { - nvim.borrow().unwrap().command(&format!("e {}", path)).map_err( - NvimInitError::new_post_init, - )?; + nvim.borrow() + .unwrap() + .command(&format!("e {}", path)) + .map_err(NvimInitError::new_post_init)?; } Ok(()) @@ -159,7 +169,7 @@ pub fn post_start_init( pub trait ErrorReport { fn report_err(&self, nvim: &mut NeovimApi); - fn ok_and_report(self, nvim: &mut NeovimApi) -> Option; + fn ok_and_report(self, nvim: &mut NeovimApi) -> Option; } impl ErrorReport for result::Result { @@ -175,4 +185,3 @@ impl ErrorReport for result::Result { self.ok() } } - diff --git a/src/nvim/redraw_handler.rs b/src/nvim/redraw_handler.rs index 59f3390..c1c1e83 100644 --- a/src/nvim/redraw_handler.rs +++ b/src/nvim/redraw_handler.rs @@ -1,4 +1,5 @@ use std::result; +use std::collections::HashMap; use neovim_lib::{Value, UiOption}; use neovim_lib::neovim_api::Tabpage; @@ -6,6 +7,7 @@ use neovim_lib::neovim_api::Tabpage; use shell; use value::ValueMapExt; +use rmpv; use super::repaint_mode::RepaintMode; use super::mode_info::ModeInfo; @@ -21,7 +23,7 @@ pub trait RedrawEvents { fn on_redraw(&mut self, mode: &RepaintMode); - fn on_highlight_set(&mut self, attrs: &[(Value, Value)]) -> RepaintMode; + fn on_highlight_set(&mut self, attrs: HashMap) -> RepaintMode; fn on_eol_clear(&mut self) -> RepaintMode; @@ -64,6 +66,16 @@ pub trait RedrawEvents { cursor_style_enabled: bool, mode_info: Vec, ) -> RepaintMode; + + fn cmdline_show( + &mut self, + content: Vec<(HashMap, String)>, + pos: u64, + firstc: String, + prompt: String, + indent: u64, + level: u64, + ) -> RepaintMode; } pub trait GuiApi { @@ -103,6 +115,31 @@ macro_rules! map_array { ); } +macro_rules! try_arg { + ($value:expr, bool) => (try_bool!($value)); + ($value:expr, uint) => (try_uint!($value)); + ($value:expr, str) => ( + match $value { + Value::String(s) => { + if let Some(s) = s.into_str() { + Ok(s) + } else { + Err("Can't convert to utf8 string".to_owned()) + } + } + _ => Err("Can't convert to string".to_owned()), + }?); + ($value:expr, ext) => (rmpv::ext::from_value($value).map_err(|e| e.to_string())?); +} + +macro_rules! call { + ($s:ident -> $c:ident ($args:ident : $($arg_type:ident),+ )) => ( + { + let mut iter = $args.into_iter(); + $s.$c($( try_arg!(iter.next().unwrap(), $arg_type)),+ ) + } + ) +} pub fn call_gui_event( ui: &mut shell::State, @@ -140,7 +177,7 @@ pub fn call_gui_event( pub fn call( ui: &mut shell::State, method: &str, - args: &[Value], + args: Vec, ) -> result::Result { let repaint_mode = match method { "cursor_goto" => ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1])), @@ -148,21 +185,12 @@ pub fn call( "clear" => ui.on_clear(), "resize" => ui.on_resize(try_uint!(args[0]), try_uint!(args[1])), "highlight_set" => { - if let Value::Map(ref attrs) = args[0] { - ui.on_highlight_set(attrs); - } else { - panic!("Supports only map value as argument"); - } + call!(ui->on_highlight_set(args: ext)); RepaintMode::Nothing } "eol_clear" => ui.on_eol_clear(), "set_scroll_region" => { - ui.on_set_scroll_region( - try_uint!(args[0]), - try_uint!(args[1]), - try_uint!(args[2]), - try_uint!(args[3]), - ); + call!(ui->on_set_scroll_region(args: uint, uint, uint, uint)); RepaintMode::Nothing } "scroll" => ui.on_scroll(try_int!(args[0])), @@ -221,6 +249,7 @@ pub fn call( )?; ui.mode_info_set(try_bool!(args[0]), mode_info) } + "cmdline_show" => call!(ui->cmdline_show(args: ext, uint, str, str, uint, uint)), _ => { println!("Event {}({:?})", method, args); RepaintMode::Nothing @@ -229,4 +258,3 @@ pub fn call( Ok(repaint_mode) } - diff --git a/src/shell.rs b/src/shell.rs index 6726608..a10a2ae 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use std::sync::{Arc, Condvar, Mutex}; use std::ops::Deref; use std::thread; +use std::collections::HashMap; use cairo; use pangocairo::CairoContextExt; @@ -20,8 +21,10 @@ use neovim_lib::neovim_api::Tabpage; use settings::{Settings, FontSource}; use ui_model::{UiModel, Attrs, ModelRect}; use color::{ColorModel, Color, COLOR_BLACK, COLOR_WHITE, COLOR_RED}; -use nvim; -use nvim::{RedrawEvents, GuiApi, RepaintMode, ErrorReport, NeovimClient, NeovimRef, NeovimClientAsync}; + +use nvim::{self, RedrawEvents, GuiApi, RepaintMode, ErrorReport, NeovimClient, NeovimRef, + NeovimClientAsync, CmdLine}; + use input; use input::keyval_to_input_string; use cursor::Cursor; @@ -599,7 +602,8 @@ impl Deref for Shell { fn gtk_focus_in(state: &mut State) -> Inhibit { if let Some(mut nvim) = state.nvim() { - nvim.command("if exists('#FocusGained') | doautocmd FocusGained | endif").report_err(&mut *nvim); + nvim.command("if exists('#FocusGained') | doautocmd FocusGained | endif") + .report_err(&mut *nvim); } state.im_context.focus_in(); @@ -611,7 +615,8 @@ fn gtk_focus_in(state: &mut State) -> Inhibit { fn gtk_focus_out(state: &mut State) -> Inhibit { if let Some(mut nvim) = state.nvim() { - nvim.command("if exists('#FocusLost') | doautocmd FocusLost | endif").report_err(&mut *nvim); + nvim.command("if exists('#FocusLost') | doautocmd FocusLost | endif") + .report_err(&mut *nvim); } state.im_context.focus_out(); @@ -959,38 +964,8 @@ impl RedrawEvents for State { RepaintMode::Area(self.model.scroll(count)) } - fn on_highlight_set(&mut self, attrs: &[(Value, Value)]) -> RepaintMode { - let mut model_attrs = Attrs::new(); - - for &(ref key_val, ref val) in attrs { - if let Some(key) = key_val.as_str() { - match key { - "foreground" => { - if let Some(fg) = val.as_u64() { - model_attrs.foreground = Some(Color::from_indexed_color(fg)); - } - } - "background" => { - if let Some(bg) = val.as_u64() { - model_attrs.background = Some(Color::from_indexed_color(bg)); - } - } - "special" => { - if let Some(bg) = val.as_u64() { - model_attrs.special = Some(Color::from_indexed_color(bg)); - } - } - "reverse" => model_attrs.reverse = true, - "bold" => model_attrs.bold = true, - "italic" => model_attrs.italic = true, - "underline" => model_attrs.underline = true, - "undercurl" => model_attrs.undercurl = true, - attr_key => println!("unknown attribute {}", attr_key), - }; - } else { - panic!("attr key must be string"); - } - } + fn on_highlight_set(&mut self, attrs: HashMap) -> RepaintMode { + let model_attrs = Attrs::from_value_map(&attrs); self.cur_attrs = Some(model_attrs); RepaintMode::Nothing @@ -1094,6 +1069,19 @@ impl RedrawEvents for State { self.mode.set_info(cursor_style_enabled, mode_info); RepaintMode::Nothing } + + fn cmdline_show( + &mut self, + content: Vec<(HashMap, String)>, + pos: u64, + firstc: String, + prompt: String, + indent: u64, + level: u64, + ) -> RepaintMode { + // TODO: implement + RepaintMode::Nothing + } } impl GuiApi for State { diff --git a/src/ui_model/cell.rs b/src/ui_model/cell.rs index b2a5a57..b981ed0 100644 --- a/src/ui_model/cell.rs +++ b/src/ui_model/cell.rs @@ -1,4 +1,7 @@ +use std::collections::HashMap; + use color::Color; +use neovim_lib::Value; #[derive(Clone)] pub struct Attrs { @@ -28,6 +31,38 @@ impl Attrs { } } + pub fn from_value_map(attrs: &HashMap) -> Attrs { + let mut model_attrs = Attrs::new(); + + for (ref key, ref val) in attrs { + match key.as_ref() { + "foreground" => { + if let Some(fg) = val.as_u64() { + model_attrs.foreground = Some(Color::from_indexed_color(fg)); + } + } + "background" => { + if let Some(bg) = val.as_u64() { + model_attrs.background = Some(Color::from_indexed_color(bg)); + } + } + "special" => { + if let Some(bg) = val.as_u64() { + model_attrs.special = Some(Color::from_indexed_color(bg)); + } + } + "reverse" => model_attrs.reverse = true, + "bold" => model_attrs.bold = true, + "italic" => model_attrs.italic = true, + "underline" => model_attrs.underline = true, + "undercurl" => model_attrs.undercurl = true, + attr_key => error!("unknown attribute {}", attr_key), + }; + } + + model_attrs + } + fn clear(&mut self) { self.italic = false; self.bold = false;