use std::error; use std::fmt; use rmpv::Value; use skulpin::skia_safe::Color4f; use crate::editor::{Colors, Style, CursorMode, CursorShape}; #[derive(Debug, Clone)] pub enum EventParseError { InvalidArray(Value), InvalidMap(Value), InvalidString(Value), InvalidU64(Value), InvalidI64(Value), InvalidBool(Value), InvalidEventFormat } type Result = std::result::Result; impl fmt::Display for EventParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { EventParseError::InvalidArray(value) => write!(f, "invalid array format {}", value), EventParseError::InvalidMap(value) => write!(f, "invalid map format {}", value), EventParseError::InvalidString(value) => write!(f, "invalid string format {}", value), EventParseError::InvalidU64(value) => write!(f, "invalid u64 format {}", value), EventParseError::InvalidI64(value) => write!(f, "invalid i64 format {}", value), EventParseError::InvalidBool(value) => write!(f, "invalid bool format {}", value), EventParseError::InvalidEventFormat => write!(f, "invalid event format") } } } impl error::Error for EventParseError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { None } } #[derive(Debug)] pub struct GridLineCell { pub text: String, pub highlight_id: Option, pub repeat: Option } pub type StyledContent = Vec<(u64, String)>; #[derive(Debug)] pub enum MessageKind { Unknown, Confirm, ConfirmSubstitute, Error, Echo, EchoMessage, EchoError, LuaError, RpcError, ReturnPrompt, QuickFix, SearchCount, Warning } impl MessageKind { pub fn parse(kind: &str) -> MessageKind { match kind { "confirm" => MessageKind::Confirm, "confirm_sub" => MessageKind::ConfirmSubstitute, "emsg" => MessageKind::Error, "echo" => MessageKind::Echo, "echomsg" => MessageKind::EchoMessage, "echoerr" => MessageKind::EchoError, "lua_error" => MessageKind::LuaError, "rpc_error" => MessageKind::RpcError, "return_prompt" => MessageKind::ReturnPrompt, "quickfix" => MessageKind::QuickFix, "search_count" => MessageKind::SearchCount, "wmsg" => MessageKind::Warning, _ => MessageKind::Unknown } } } #[derive(Debug)] pub enum RedrawEvent { SetTitle { title: String }, ModeInfoSet { cursor_modes: Vec }, ModeChange { mode_index: u64 }, BusyStart, BusyStop, Flush, Resize { grid: u64, width: u64, height: u64 }, DefaultColorsSet { colors: Colors }, HighlightAttributesDefine { id: u64, style: Style }, GridLine { grid: u64, row: u64, column_start: u64, cells: Vec }, Clear { grid: u64 }, CursorGoto { grid: u64, row: u64, column: u64 }, Scroll { grid: u64, top: u64, bottom: u64, left: u64, right: u64, rows: i64, columns: i64 }, CommandLineShow { content: StyledContent, position: u64, first_character: String, prompt: String, indent: u64, level: u64 }, CommandLinePosition { position: u64, level: u64 }, CommandLineSpecialCharacter { character: String, shift: bool, level: u64 }, CommandLineHide, CommandLineBlockShow { lines: Vec }, CommandLineBlockAppend { line: StyledContent }, CommandLineBlockHide, MessageShow { kind: MessageKind, content: StyledContent, replace_last: bool }, MessageClear, MessageShowMode { content: StyledContent }, MessageShowCommand { content: StyledContent }, MessageRuler { content: StyledContent }, MessageHistoryShow { entries: Vec<(MessageKind, StyledContent)>} } fn unpack_color(packed_color: u64) -> Color4f { let packed_color = packed_color as u32; let r = ((packed_color & 0xff0000) >> 16) as f32; let g = ((packed_color & 0xff00) >> 8) as f32; let b = (packed_color & 0xff) as f32; Color4f { r: r / 255.0, g: g / 255.0, b: b / 255.0, a: 1.0 } } fn parse_array(array_value: &Value) -> Result> { if let Value::Array(content) = array_value.clone() { Ok(content.to_vec()) } else { Err(EventParseError::InvalidArray(array_value.clone())) } } fn parse_map(map_value: &Value) -> Result> { if let Value::Map(content) = map_value.clone() { Ok(content) } else { Err(EventParseError::InvalidMap(map_value.clone())) } } fn parse_string(string_value: &Value) -> Result { if let Value::String(content) = string_value.clone() { Ok(content.into_str().ok_or(EventParseError::InvalidString(string_value.clone()))?) } else { Err(EventParseError::InvalidString(string_value.clone())) } } fn parse_u64(u64_value: &Value) -> Result { if let Value::Integer(content) = u64_value.clone() { Ok(content.as_u64().ok_or(EventParseError::InvalidU64(u64_value.clone()))?) } else { Err(EventParseError::InvalidU64(u64_value.clone())) } } fn parse_i64(i64_value: &Value) -> Result { if let Value::Integer(content) = i64_value.clone() { Ok(content.as_i64().ok_or(EventParseError::InvalidI64(i64_value.clone()))?) } else { Err(EventParseError::InvalidI64(i64_value.clone())) } } fn parse_bool(bool_value: &Value) -> Result { if let Value::Boolean(content) = bool_value.clone() { Ok(content) } else { Err(EventParseError::InvalidBool(bool_value.clone())) } } fn parse_set_title(set_title_arguments: Vec) -> Result { if let [title] = set_title_arguments.as_slice() { Ok(RedrawEvent::SetTitle { title: parse_string(title)? }) } else { Err(EventParseError::InvalidEventFormat) } } fn parse_mode_info_set(mode_info_set_arguments: Vec) -> Result { if let [_cursor_style_enabled, mode_info] = mode_info_set_arguments.as_slice() { let mode_info_values = parse_array(mode_info)?; let mut cursor_modes = Vec::new(); for mode_info_value in mode_info_values { let info_map = parse_map(&mode_info_value)?; let mut mode_info = CursorMode::new(); for (name, value) in info_map { let name = parse_string(&name)?; match name.as_ref() { "cursor_shape" => { mode_info.shape = CursorShape::from_type_name(&parse_string(&value)?); }, "attr_id" => { mode_info.style_id = Some(parse_u64(&value)?); }, _ => {} } } cursor_modes.push(mode_info); } Ok(RedrawEvent::ModeInfoSet { cursor_modes }) } else { Err(EventParseError::InvalidEventFormat) } } fn parse_mode_change(mode_change_arguments: Vec) -> Result { if let [_mode, mode_index] = mode_change_arguments.as_slice() { Ok(RedrawEvent::ModeChange { mode_index: parse_u64(&mode_index)? }) } else { Err(EventParseError::InvalidEventFormat) } } fn parse_grid_resize(grid_resize_arguments: Vec) -> Result { if let [grid_id, width, height] = grid_resize_arguments.as_slice() { Ok(RedrawEvent::Resize { grid: parse_u64(&grid_id)?, width: parse_u64(&width)?, height: parse_u64(&height)? }) } else { Err(EventParseError::InvalidEventFormat) } } fn parse_default_colors(default_colors_arguments: Vec) -> Result { if let [ foreground, background, special, _term_foreground, _term_background ] = default_colors_arguments.as_slice() { Ok(RedrawEvent::DefaultColorsSet { colors: Colors { foreground: Some(unpack_color(parse_u64(&foreground)?)), background: Some(unpack_color(parse_u64(&background)?)), special: Some(unpack_color(parse_u64(special)?)), } }) } else { Err(EventParseError::InvalidEventFormat) } } fn parse_style(style_map: &Value) -> Result