mirror of https://github.com/sgoudham/neovide.git
colors working
parent
6ca852386f
commit
ef8eef6bd3
@ -1,51 +1,184 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::collections::HashMap;
|
||||||
|
use druid_shell::piet::Color;
|
||||||
|
|
||||||
use druid_shell::piet::PietTextLayout;
|
use neovim_lib::{Neovim, NeovimApi};
|
||||||
|
|
||||||
use neovim_lib::Neovim;
|
#[derive(new, Debug, Clone)]
|
||||||
|
pub struct Colors {
|
||||||
|
pub foreground: Option<Color>,
|
||||||
|
pub background: Option<Color>,
|
||||||
|
pub special: Option<Color>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Colors {
|
||||||
|
fn eq(&self, other: &Colors) -> bool {
|
||||||
|
fn compare_options(a: &Option<Color>, b: &Option<Color>) -> bool {
|
||||||
|
match (a, b) {
|
||||||
|
(Some(a), Some(b)) => a.as_rgba_u32() == b.as_rgba_u32(),
|
||||||
|
(None, None) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compare_options(&self.foreground, &other.foreground) &&
|
||||||
|
compare_options(&self.background, &other.background) &&
|
||||||
|
compare_options(&self.special, &other.special)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Derivative, new)]
|
#[derive(new, Debug, Clone, PartialEq)]
|
||||||
#[derivative(PartialEq)]
|
pub struct Style {
|
||||||
|
pub colors: Colors,
|
||||||
|
#[new(default)]
|
||||||
|
pub reverse: bool,
|
||||||
|
#[new(default)]
|
||||||
|
pub italic: bool,
|
||||||
|
#[new(default)]
|
||||||
|
pub bold: bool,
|
||||||
|
#[new(default)]
|
||||||
|
pub strikethrough: bool,
|
||||||
|
#[new(default)]
|
||||||
|
pub underline: bool,
|
||||||
|
#[new(default)]
|
||||||
|
pub undercurl: bool,
|
||||||
|
#[new(default)]
|
||||||
|
pub blend: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(new)]
|
||||||
|
pub struct GridLineCell {
|
||||||
|
pub grid: u16,
|
||||||
|
pub text: String,
|
||||||
|
pub row: u16,
|
||||||
|
pub col_start: u16,
|
||||||
|
pub style_id: Option<u64>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type GridCell = Option<(char, Style)>;
|
||||||
|
|
||||||
|
#[derive(new, Debug, Clone)]
|
||||||
pub struct DrawCommand {
|
pub struct DrawCommand {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
pub row: u64,
|
pub row: u16,
|
||||||
pub col_start: u64,
|
pub col_start: u16,
|
||||||
#[new(default)]
|
pub style: Style
|
||||||
#[derivative(PartialEq="ignore")]
|
|
||||||
pub layout: Mutex<Option<PietTextLayout>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Editor {
|
pub struct Editor {
|
||||||
pub nvim: Neovim,
|
pub nvim: Neovim,
|
||||||
pub draw_commands: Vec<Vec<Arc<Option<DrawCommand>>>>,
|
pub grid: Vec<Vec<GridCell>>,
|
||||||
|
pub cursor_pos: (u16, u16),
|
||||||
|
pub size: (u16, u16),
|
||||||
|
pub default_colors: Colors,
|
||||||
|
pub defined_styles: HashMap<u64, Style>,
|
||||||
|
pub previous_style: Option<Style>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Editor {
|
impl Editor {
|
||||||
pub fn new(nvim: Neovim, width: usize, height: usize) -> Editor {
|
pub fn new(nvim: Neovim, width: u16, height: u16) -> Editor {
|
||||||
let mut draw_commands = Vec::with_capacity(height);
|
let mut editor = Editor {
|
||||||
for _ in 0..width {
|
|
||||||
draw_commands.push(vec![Arc::new(None); width]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Editor {
|
|
||||||
nvim,
|
nvim,
|
||||||
|
grid: Vec::new(),
|
||||||
|
cursor_pos: (0, 0),
|
||||||
|
size: (width, height),
|
||||||
|
default_colors: Colors::new(Some(Color::rgb(0xff, 0xff, 0xff)), Some(Color::rgb(0x00, 0x00, 0x00)), Some(Color::rgb(0x88, 0x88, 0x88))),
|
||||||
|
defined_styles: HashMap::new(),
|
||||||
|
previous_style: None
|
||||||
|
};
|
||||||
|
editor.clear();
|
||||||
|
editor
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_draw_commands(&self) -> Vec<DrawCommand> {
|
||||||
|
self.grid.iter().enumerate().map(|(row_index, row)| {
|
||||||
|
let mut draw_commands = Vec::new();
|
||||||
|
let mut command = None;
|
||||||
|
|
||||||
|
fn add_command(commands_list: &mut Vec<DrawCommand>, command: Option<DrawCommand>) {
|
||||||
|
if let Some(command) = command {
|
||||||
|
commands_list.push(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn command_matches(command: &Option<DrawCommand>, style: &Style) -> bool {
|
||||||
|
match command {
|
||||||
|
Some(command) => &command.style == style,
|
||||||
|
None => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_character(command: &mut Option<DrawCommand>, character: &char, row_index: u16, col_index: u16, style: Style) {
|
||||||
|
match command {
|
||||||
|
Some(command) => command.text.push(character.clone()),
|
||||||
|
None => {
|
||||||
|
command.replace(DrawCommand::new(character.to_string(), row_index, col_index, style));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (col_index, cell) in row.iter().enumerate() {
|
||||||
|
if let Some((character, new_style)) = cell {
|
||||||
|
if !command_matches(&command, &new_style) {
|
||||||
|
add_command(&mut draw_commands, command);
|
||||||
|
command = None;
|
||||||
|
}
|
||||||
|
add_character(&mut command, &character, row_index as u16, col_index as u16, new_style.clone());
|
||||||
|
} else {
|
||||||
|
add_command(&mut draw_commands, command);
|
||||||
|
command = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_command(&mut draw_commands, command);
|
||||||
|
|
||||||
draw_commands
|
draw_commands
|
||||||
}
|
}).flatten().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&mut self, command: DrawCommand) {
|
pub fn draw(&mut self, command: GridLineCell) {
|
||||||
let length = command.text.chars().count();
|
|
||||||
let row_index = command.row as usize;
|
let row_index = command.row as usize;
|
||||||
let col_start = command.col_start as usize;
|
let col_start = command.col_start as usize;
|
||||||
let pointer = Arc::new(Some(command));
|
|
||||||
|
|
||||||
let row = self.draw_commands.get_mut(row_index).expect("Draw command out of bounds");
|
let style = match (command.style_id, self.previous_style.clone()) {
|
||||||
|
(Some(0), _) => Style::new(self.default_colors.clone()),
|
||||||
|
(Some(style_id), _) => self.defined_styles.get(&style_id).expect("GridLineCell must use defined color").clone(),
|
||||||
|
(None, Some(previous_style)) => previous_style,
|
||||||
|
(None, None) => Style::new(self.default_colors.clone())
|
||||||
|
};
|
||||||
|
|
||||||
for x in 0..length {
|
if row_index < self.grid.len() {
|
||||||
let pointer_index = x + col_start;
|
let row = self.grid.get_mut(row_index).expect("Grid must have size greater than row_index");
|
||||||
if pointer_index < row.len() {
|
for (i, character) in command.text.chars().enumerate() {
|
||||||
row[pointer_index] = pointer.clone();
|
let pointer_index = i + col_start;
|
||||||
|
if pointer_index < row.len() {
|
||||||
|
row[pointer_index] = Some((character, style.clone()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
println!("Draw command out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.previous_style = Some(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
let (width, height) = self.size;
|
||||||
|
self.grid = vec![vec![None; width as usize]; height as usize];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&mut self, new_width: u16, new_height: u16) {
|
||||||
|
self.nvim.ui_try_resize(new_width as i64, new_height as i64).expect("Resize failed");
|
||||||
|
self.size = (new_width, new_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn define_style(&mut self, id: u64, style: Style) {
|
||||||
|
self.defined_styles.insert(id, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_default_colors(&mut self, foreground: Color, background: Color, special: Color) {
|
||||||
|
self.default_colors = Colors::new(Some(foreground), Some(background), Some(special));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn jump_cursor_to(&mut self, row: u16, col: u16) {
|
||||||
|
self.cursor_pos = (row, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue