Different, cleaner implementation of structured settings

macos-click-through
Jon Valdés 5 years ago
parent 40dd9404ec
commit 0a726c2f77

@ -15,10 +15,10 @@ use log::{info, error, trace};
pub use events::*; pub use events::*;
pub use keybindings::*; pub use keybindings::*;
use crate::settings::*;
pub use ui_commands::UiCommand; pub use ui_commands::UiCommand;
use handler::NeovimHandler; use handler::NeovimHandler;
use crate::error_handling::ResultPanicExplanation; use crate::error_handling::ResultPanicExplanation;
use crate::settings::SETTINGS;
use crate::INITIAL_DIMENSIONS; use crate::INITIAL_DIMENSIONS;

@ -1,12 +1,15 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#[macro_use]
mod settings;
mod bridge; mod bridge;
mod editor; mod editor;
mod window; mod window;
mod renderer; mod renderer;
mod error_handling; mod error_handling;
mod redraw_scheduler; mod redraw_scheduler;
mod settings;
#[macro_use] extern crate derive_new; #[macro_use] extern crate derive_new;
#[macro_use] extern crate rust_embed; #[macro_use] extern crate rust_embed;

@ -4,7 +4,7 @@ use std::time::Instant;
use log::trace; use log::trace;
use crate::settings::{SETTINGS, Value}; use crate::settings::*;
lazy_static! { lazy_static! {
pub static ref REDRAW_SCHEDULER: RedrawScheduler = RedrawScheduler::new(); pub static ref REDRAW_SCHEDULER: RedrawScheduler = RedrawScheduler::new();
@ -15,28 +15,13 @@ struct RedrawSettings {
extra_buffer_frames: u64, extra_buffer_frames: u64,
} }
fn parse_changed_setting(name: &str, value: Option<Value>) -> Value {
match name {
"extra_buffer_frames" => {
let mut settings = SETTINGS.get::<RedrawSettings>();
if let Some(value) = value {
settings.extra_buffer_frames = value.as_u64().unwrap(); // TODO -- handle wrong data type
SETTINGS.set(&settings);
}
Value::from(settings.extra_buffer_frames)
}
_ => {
panic!(format!("Unknown setting: {}", name));
}
}
}
pub fn initialize_settings() { pub fn initialize_settings() {
SETTINGS.set(&RedrawSettings { SETTINGS.set(&RedrawSettings {
extra_buffer_frames: 60, extra_buffer_frames: 60,
}); });
SETTINGS.add_listener("extra_buffer_frames", parse_changed_setting); register_nvim_setting!("extra_buffer_frames", RedrawSettings::extra_buffer_frames);
} }
pub struct RedrawScheduler { pub struct RedrawScheduler {

@ -16,6 +16,85 @@ lazy_static! {
pub static ref SETTINGS: Settings = Settings::new(); pub static ref SETTINGS: Settings = Settings::new();
} }
pub trait FromValue {
fn from_value(&mut self, value: Value);
}
impl FromValue for f32 {
fn from_value(&mut self, value: Value) {
// TODO -- Warn when incorrect type
if value.is_f32() {
*self = value.as_f64().unwrap() as f32;
}
}
}
impl FromValue for u64 {
fn from_value(&mut self, value: Value) {
// TODO -- Warn when incorrect type
if value.is_u64() {
*self = value.as_u64().unwrap();
}
}
}
impl FromValue for u32 {
fn from_value(&mut self, value: Value) {
// TODO -- Warn when incorrect type
if value.is_u64() {
*self = value.as_u64().unwrap() as u32;
}
}
}
impl FromValue for i32 {
fn from_value(&mut self, value: Value) {
// TODO -- Warn when incorrect type
if value.is_i64() {
*self = value.as_i64().unwrap() as i32;
}
}
}
impl FromValue for String {
fn from_value(&mut self, value: Value) {
// TODO -- Warn when incorrect type
if value.is_str() {
*self = String::from(value.as_str().unwrap());
}
}
}
impl FromValue for bool {
fn from_value(&mut self, value: Value) {
// TODO -- Warn when incorrect type
if value.is_bool() {
*self = value.as_bool().unwrap();
}
}
}
#[macro_export]
macro_rules! register_nvim_setting {
($vim_setting_name: expr, $type_name:ident :: $field_name: ident) => {{
fn update_func(value: Value) {
let mut s = SETTINGS.get::<$type_name>();
s.$field_name.from_value(value);
SETTINGS.set(&s);
}
fn reader_func() -> Value {
let s = SETTINGS.get::<$type_name>();
s.$field_name.into()
}
SETTINGS.add_handlers($vim_setting_name, update_func, reader_func);
}};
}
type UpdateHandlerFunc = fn(Value);
type ReaderFunc = fn()->Value;
struct SettingsObject { struct SettingsObject {
object: Box<dyn Any + Send + Sync>, object: Box<dyn Any + Send + Sync>,
} }
@ -23,7 +102,8 @@ struct SettingsObject {
pub struct Settings { pub struct Settings {
pub neovim_arguments: Vec<String>, pub neovim_arguments: Vec<String>,
settings: RwLock<HashMap<TypeId, SettingsObject>>, settings: RwLock<HashMap<TypeId, SettingsObject>>,
listeners: RwLock<HashMap<String, fn (&str, Option<Value>)->Value>>, listeners: RwLock<HashMap<String, UpdateHandlerFunc>>,
readers: RwLock<HashMap<String, ReaderFunc>>,
} }
impl Settings { impl Settings {
@ -33,6 +113,8 @@ impl Settings {
let mut no_idle = false; let mut no_idle = false;
let mut buffer_frames = 1; let mut buffer_frames = 1;
// TODO -- Make command line parsing work again
let neovim_arguments = std::env::args().filter(|arg| { let neovim_arguments = std::env::args().filter(|arg| {
if arg == "--log" { if arg == "--log" {
Logger::with_str("neovide") Logger::with_str("neovide")
@ -57,11 +139,13 @@ impl Settings {
neovim_arguments, neovim_arguments,
settings: RwLock::new(HashMap::new()), settings: RwLock::new(HashMap::new()),
listeners: RwLock::new(HashMap::new()), listeners: RwLock::new(HashMap::new()),
readers: RwLock::new(HashMap::new()),
} }
} }
pub fn add_listener(&self, property_name: &str, func: fn (&str, Option<Value>)-> Value) { pub fn add_handlers(&self, property_name: &str, update_func: UpdateHandlerFunc, reader_func: ReaderFunc) {
self.listeners.write().insert(String::from(property_name), func); self.listeners.write().insert(String::from(property_name), update_func);
self.readers.write().insert(String::from(property_name), reader_func);
} }
pub fn set<T: Clone + Send + Sync + 'static >(&self, t: &T) { pub fn set<T: Clone + Send + Sync + 'static >(&self, t: &T) {
@ -83,11 +167,11 @@ impl Settings {
let variable_name = format!("neovide_{}", name.to_string()); let variable_name = format!("neovide_{}", name.to_string());
match nvim.get_var(&variable_name).await { match nvim.get_var(&variable_name).await {
Ok(value) => { Ok(value) => {
self.listeners.read().get(&name).unwrap()(&name, Some(value)); self.listeners.read().get(&name).unwrap()(value);
}, },
Err(error) => { Err(error) => {
warn!("Initial value load failed for {}: {}", name, error); warn!("Initial value load failed for {}: {}", name, error);
let setting = self.listeners.read().get(&name).unwrap()(&name, None); let setting = self.readers.read().get(&name).unwrap()();
nvim.set_var(&variable_name, setting).await.ok(); nvim.set_var(&variable_name, setting).await.ok();
} }
} }
@ -118,40 +202,6 @@ impl Settings {
let name: Result<String, _>= name.try_into(); let name: Result<String, _>= name.try_into();
let name = name.unwrap(); let name = name.unwrap();
self.listeners.read().get(&name).unwrap()(&name, Some(value)); self.listeners.read().get(&name).unwrap()(value);
}
/*
pub fn new() -> Settings {
let mut no_idle = false;
let mut buffer_frames = 1;
let neovim_arguments = std::env::args().filter(|arg| {
if arg == "--log" {
Logger::with_str("neovide")
.log_to_file()
.rotate(Criterion::Size(10_000_000), Naming::Timestamps, Cleanup::KeepLogFiles(1))
.start()
.expect("Could not start logger");
false
} else if arg == "--noIdle" {
no_idle = true;
false
} else if arg == "--extraBufferFrames" {
buffer_frames = 60;
false
} else {
true
}
}).collect::<Vec<String>>();
let mut settings = HashMap::new();
settings.insert("no_idle".to_string(), Setting::new_bool(no_idle));
settings.insert("extra_buffer_frames".to_string(), Setting::new_u16(buffer_frames));
settings.insert("refresh_rate".to_string(), Setting::new_u16(60));
Settings { neovim_arguments, settings: Mutex::new(settings) }
} }
*/
} }

@ -10,11 +10,11 @@ use skulpin::sdl2::event::Event;
use skulpin::sdl2::keyboard::{Mod, Keycode}; use skulpin::sdl2::keyboard::{Mod, Keycode};
use skulpin::{RendererBuilder, Renderer as SkulpinRenderer, PresentMode, CoordinateSystem, dpis}; use skulpin::{RendererBuilder, Renderer as SkulpinRenderer, PresentMode, CoordinateSystem, dpis};
use crate::settings::*;
use crate::bridge::{parse_keycode, append_modifiers, BRIDGE, UiCommand}; use crate::bridge::{parse_keycode, append_modifiers, BRIDGE, UiCommand};
use crate::renderer::Renderer; use crate::renderer::Renderer;
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::editor::EDITOR; use crate::editor::EDITOR;
use crate::settings::{SETTINGS, Value};
use crate::INITIAL_DIMENSIONS; use crate::INITIAL_DIMENSIONS;
#[derive(RustEmbed)] #[derive(RustEmbed)]
@ -257,37 +257,14 @@ struct WindowSettings {
no_idle: bool, no_idle: bool,
} }
fn parse_changed_setting(name: &str, value: Option<Value>) -> Value {
let mut settings = SETTINGS.get::<WindowSettings>();
match name {
"refresh_rate" => {
if let Some(value) = value {
settings.refresh_rate = value.as_u64().unwrap(); // TODO -- handle wrong data type
SETTINGS.set(&settings);
}
Value::from(settings.refresh_rate)
},
"no_idle" => {
if let Some(value) = value {
settings.no_idle = value.as_bool().unwrap(); // TODO -- handle wrong data type
SETTINGS.set(&settings);
}
Value::from(settings.no_idle)
},
_ => {
panic!(format!("Unknown setting: {}", name));
}
}
}
pub fn initialize_settings() { pub fn initialize_settings() {
SETTINGS.set(&WindowSettings { SETTINGS.set(&WindowSettings {
refresh_rate: 60, refresh_rate: 60,
no_idle: false, no_idle: false,
}); });
SETTINGS.add_listener("refresh_rate", parse_changed_setting); register_nvim_setting!("refresh_rate", WindowSettings::refresh_rate);
SETTINGS.add_listener("no_idle", parse_changed_setting); register_nvim_setting!("no_idle", WindowSettings::no_idle);
} }
pub fn ui_loop() { pub fn ui_loop() {

Loading…
Cancel
Save