Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Better Configuration/Settings #2143

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions neovide-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,24 @@ fn struct_stream(name: Ident, prefix: String, data: &DataStruct) -> TokenStream
// Only create a reader function for global neovide variables
let reader = if option_name.is_none() {
quote! {
fn reader(settings: &crate::settings::Settings) -> Option<rmpv::Value> {
fn reader(settings: &crate::settings::SettingsManager) -> Option<rmpv::Value> {
let s = settings.get::<#name>();
Some(s.#ident.into())
}
}
} else {
quote! {
fn reader(_settings: &crate::settings::Settings) -> Option<rmpv::Value> {
fn reader(_settings: &crate::settings::SettingsManager) -> Option<rmpv::Value> {
None
}
}
};

quote! {{
fn update(settings: &crate::settings::Settings, value: rmpv::Value, send_changed_event: bool) {
fn update(settings: &crate::settings::SettingsManager, value: rmpv::Value, send_changed_event: bool) {
let mut s = settings.get::<#name>();
s.#ident.parse_from_value(value);

crate::settings::ParseFromValue::parse_from_value(&mut s.#ident, value);
settings.set(&s);
if send_changed_event {
crate::event_aggregator::EVENT_AGGREGATOR.send(
Expand All @@ -86,7 +87,7 @@ fn struct_stream(name: Ident, prefix: String, data: &DataStruct) -> TokenStream

#reader

settings.set_setting_handlers(
nvim_state.set_setting_handlers(
#location,
update,
reader,
Expand Down Expand Up @@ -115,10 +116,10 @@ fn struct_stream(name: Ident, prefix: String, data: &DataStruct) -> TokenStream

impl crate::settings::SettingGroup for #name {
type ChangedEvent = #event_name;
fn register(settings: &crate::settings::Settings) {
fn register(nvim_state: &crate::settings::NvimStateManager) -> Self {
let s: Self = Default::default();
settings.set(&s);
#(#listener_fragments)*
s
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/bridge/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use anyhow::{bail, Result};
use log::debug;
use tokio::process::Command as TokioCommand;

use crate::{cmd_line::CmdLineSettings, settings::*};
use crate::settings::*;

pub fn create_nvim_command() -> Result<TokioCommand> {
let mut cmd = build_nvim_cmd()?;
Expand Down
6 changes: 3 additions & 3 deletions src/bridge/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
error_handling::ResultPanicExplanation,
event_aggregator::EVENT_AGGREGATOR,
running_tracker::*,
settings::SETTINGS,
settings::NVIM_STATE,
window::WindowCommand,
};

Expand Down Expand Up @@ -78,10 +78,10 @@ impl Handler for NeovimHandler {
}
}
"setting_changed" => {
SETTINGS.handle_setting_changed_notification(arguments);
NVIM_STATE.handle_setting_changed_notification(arguments);
}
"option_changed" => {
SETTINGS.handle_option_changed_notification(arguments);
NVIM_STATE.handle_option_changed_notification(arguments);
}
"neovide.quit" => {
let error_code = arguments[0]
Expand Down
6 changes: 3 additions & 3 deletions src/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use tokio::{
task::JoinHandle,
};

use crate::{cmd_line::CmdLineSettings, dimensions::Dimensions, running_tracker::*, settings::*};
use crate::{dimensions::Dimensions, running_tracker::*, settings::*};
use handler::NeovimHandler;
use session::{NeovimInstance, NeovimSession};
use setup::setup_neovide_specific_state;
Expand Down Expand Up @@ -116,11 +116,11 @@ async fn launch(grid_size: Option<Dimensions>) -> Result<NeovimSession> {
setup_neovide_specific_state(&session.neovim, should_handle_clipboard).await?;

start_ui_command_handler(Arc::clone(&session.neovim));
SETTINGS.read_initial_values(&session.neovim).await?;
NVIM_STATE.read_initial_values(&session.neovim).await?;

let mut options = UiAttachOptions::new();
options.set_linegrid_external(true);
options.set_multigrid_external(!settings.no_multi_grid);
options.set_multigrid_external(!settings.no_multigrid);
options.set_rgb(true);

// Triggers loading the user config
Expand Down
4 changes: 2 additions & 2 deletions src/bridge/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rmpv::Value;
use super::setup_intro_message_autocommand;
use crate::{
bridge::NeovimWriter,
settings::{SettingLocation, SETTINGS},
settings::{SettingLocation, NVIM_STATE},
};

const INIT_LUA: &str = include_str!("../../lua/init.lua");
Expand Down Expand Up @@ -63,7 +63,7 @@ pub async fn setup_neovide_specific_state(
let register_clipboard = should_handle_clipboard;
let register_right_click = cfg!(target_os = "windows");

let settings = SETTINGS.setting_locations();
let settings = NVIM_STATE.setting_locations();
let global_variable_settings = settings
.iter()
.filter_map(|s| match s {
Expand Down
155 changes: 74 additions & 81 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ extern crate clap;
mod bridge;
mod channel_utils;
mod clipboard;
mod cmd_line;
mod dimensions;
mod editor;
mod error_handling;
Expand All @@ -34,7 +33,7 @@ extern crate lazy_static;

use anyhow::Result;
use log::trace;
use std::env::{self, args};
use std::env;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::panic::{set_hook, PanicInfo};
Expand All @@ -47,10 +46,11 @@ use flexi_logger::{Cleanup, Criterion, Duplicate, FileSpec, Logger, Naming};

use backtrace::Backtrace;
use bridge::NeovimRuntime;
use cmd_line::CmdLineSettings;
use editor::start_editor;
use error_handling::{handle_startup_errors, NeovideExitCode};
use renderer::{cursor_renderer::CursorSettings, RendererSettings};
use settings::CmdLineSettings;
#[cfg(not(test))]
use settings::SETTINGS;
use window::{
create_event_loop, create_window, determine_window_size, main_loop, WindowSettings, WindowSize,
Expand All @@ -62,13 +62,78 @@ pub use running_tracker::*;
#[cfg(target_os = "windows")]
pub use windows_utils::*;

use crate::settings::{load_last_window_settings, Config, PersistentWindowSettings};
use crate::settings::{load_last_window_settings, PersistentWindowSettings, NVIM_STATE};

pub use profiling::startup_profiler;

const BACKTRACES_FILE: &str = "neovide_backtraces.log";
const REQUEST_MESSAGE: &str = "This is a bug and we would love for it to be reported to https://github.com/neovide/neovide/issues";

// --------------
// | Architecture |
// --------------
//
// BRIDGE:
// The bridge is responsible for the connection to the neovim process itself. It is in charge
// of starting and communicating to and from the process. The bridge is async and has a
// couple of sub components:
//
// NEOVIM HANDLER:
// This component handles events from neovim sent specifically to the gui. This includes
// redraw events responsible for updating the gui state, and custom neovide specific
// events which are registered on startup and handle syncing of settings or features from
// the neovim process.
//
// UI COMMAND HANDLER:
// This component handles communication from other components to the neovim process. The
// commands are split into Serial and Parallel commands. Serial commands must be
// processed in order while parallel commands can be processed in any order and in
// parallel.
//
// EDITOR:
// The editor is responsible for processing and transforming redraw events into something
// more readily renderable. Ligature support and multi window management requires some
// significant preprocessing of the redraw events in order to capture what exactly should get
// drawn where. Further this step takes a bit of processing power to accomplish, so it is done
// on it's own thread. Ideally heavily computationally expensive tasks should be done in the
// editor.
//
// RENDERER:
// The renderer is responsible for drawing the editor's output to the screen. It uses skia
// for drawing and is responsible for maintaining the various draw surfaces which are stored
// to prevent unnecessary redraws.
//
// WINDOW:
// The window is responsible for rendering and gathering input events from the user. This
// inncludes taking the draw commands from the editor and turning them into pixels on the
// screen. The ui commands are then forwarded back to the BRIDGE to convert them into
// commands for neovim to handle properly.
//
// ------------------
// | Other Components |
// ------------------
//
// Neovide also includes some other systems which are globally available via lazy static
// instantiations.
//
// EVENT AGGREGATOR:
// Central system which distributes events to each of the other components. This is done
// using TypeIds and channels. Any component can publish any Clone + Debug + Send + Sync type
// to the aggregator, but only one component can subscribe to any type. The system takes
// pains to ensure that channels are shared by thread in order to keep things performant.
// Also tokio channels are used so that the async components can properly await for events.
//
// SETTINGS:
// The settings system is live updated from global variables in neovim with the prefix
// "neovide". They allow us to configure and manage the functionality of neovide from neovim
// init scripts and variables.
//
// REDRAW SCHEDULER:
// The redraw scheduler is a simple system in charge of deciding if the renderer should draw
// another frame next frame, or if it can safely skip drawing to save battery and cpu power.
// Multiple other parts of the app "queue_next_frame" function to ensure animations continue
// properly or updates to the graphics are pushed to the screen.

fn main() -> NeovideExitCode {
set_hook(Box::new(|panic_info| {
let backtrace = Backtrace::new();
Expand All @@ -79,11 +144,6 @@ fn main() -> NeovideExitCode {
log_panic_to_file(panic_info, &backtrace);
}));

#[cfg(target_os = "windows")]
{
windows_fix_dpi();
}

let event_loop = create_event_loop();

match setup() {
Expand All @@ -98,86 +158,19 @@ fn main() -> NeovideExitCode {
}

fn setup() -> Result<(WindowSize, NeovimRuntime)> {
// --------------
// | Architecture |
// --------------
//
// BRIDGE:
// The bridge is responsible for the connection to the neovim process itself. It is in charge
// of starting and communicating to and from the process. The bridge is async and has a
// couple of sub components:
//
// NEOVIM HANDLER:
// This component handles events from neovim sent specifically to the gui. This includes
// redraw events responsible for updating the gui state, and custom neovide specific
// events which are registered on startup and handle syncing of settings or features from
// the neovim process.
//
// UI COMMAND HANDLER:
// This component handles communication from other components to the neovim process. The
// commands are split into Serial and Parallel commands. Serial commands must be
// processed in order while parallel commands can be processed in any order and in
// parallel.
//
// EDITOR:
// The editor is responsible for processing and transforming redraw events into something
// more readily renderable. Ligature support and multi window management requires some
// significant preprocessing of the redraw events in order to capture what exactly should get
// drawn where. Further this step takes a bit of processing power to accomplish, so it is done
// on it's own thread. Ideally heavily computationally expensive tasks should be done in the
// editor.
//
// RENDERER:
// The renderer is responsible for drawing the editor's output to the screen. It uses skia
// for drawing and is responsible for maintaining the various draw surfaces which are stored
// to prevent unnecessary redraws.
//
// WINDOW:
// The window is responsible for rendering and gathering input events from the user. This
// inncludes taking the draw commands from the editor and turning them into pixels on the
// screen. The ui commands are then forwarded back to the BRIDGE to convert them into
// commands for neovim to handle properly.
//
// ------------------
// | Other Components |
// ------------------
//
// Neovide also includes some other systems which are globally available via lazy static
// instantiations.
//
// EVENT AGGREGATOR:
// Central system which distributes events to each of the other components. This is done
// using TypeIds and channels. Any component can publish any Clone + Debug + Send + Sync type
// to the aggregator, but only one component can subscribe to any type. The system takes
// pains to ensure that channels are shared by thread in order to keep things performant.
// Also tokio channels are used so that the async components can properly await for events.
//
// SETTINGS:
// The settings system is live updated from global variables in neovim with the prefix
// "neovide". They allow us to configure and manage the functionality of neovide from neovim
// init scripts and variables.
//
// REDRAW SCHEDULER:
// The redraw scheduler is a simple system in charge of deciding if the renderer should draw
// another frame next frame, or if it can safely skip drawing to save battery and cpu power.
// Multiple other parts of the app "queue_next_frame" function to ensure animations continue
// properly or updates to the graphics are pushed to the screen.
Config::init();

//Will exit if -h or -v
cmd_line::handle_command_line_arguments(args().collect())?;
settings::initialize_settings()?;
#[cfg(not(target_os = "windows"))]
maybe_disown();
startup_profiler();

#[cfg(not(test))]
init_logger();

trace!("Neovide version: {}", crate_version!());

SETTINGS.register::<WindowSettings>();
SETTINGS.register::<RendererSettings>();
SETTINGS.register::<CursorSettings>();
NVIM_STATE.register::<WindowSettings>();
NVIM_STATE.register::<RendererSettings>();
NVIM_STATE.register::<CursorSettings>();

let window_settings = load_last_window_settings().ok();
let window_size = determine_window_size(window_settings.as_ref());
let grid_size = match window_size {
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/cursor_renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
profiling::tracy_zone,
renderer::animation_utils::*,
renderer::{GridRenderer, RenderedWindow},
settings::{ParseFromValue, SETTINGS},
settings::SETTINGS,
window::UserEvent,
};

Expand Down
5 changes: 2 additions & 3 deletions src/renderer/rendered_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ use skia_safe::{
};

use crate::{
cmd_line::CmdLineSettings,
dimensions::Dimensions,
editor::{AnchorInfo, Style, WindowType},
profiling::tracy_zone,
renderer::{animation_utils::*, GridRenderer, RendererSettings},
settings::SETTINGS,
settings::{CmdLineSettings, SETTINGS},
utils::RingBuffer,
};

Expand Down Expand Up @@ -98,7 +97,7 @@ pub struct WindowDrawDetails {

impl WindowDrawDetails {
pub fn event_grid_id(&self) -> u64 {
if SETTINGS.get::<CmdLineSettings>().no_multi_grid {
if SETTINGS.get::<CmdLineSettings>().no_multigrid {
0
} else {
self.id
Expand Down
4 changes: 2 additions & 2 deletions src/cmd_line.rs → src/settings/cmd_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct CmdLineSettings {
)]
pub neovim_args: Vec<String>,

/// If to enable logging to a file in the current directory
/// Write logs out to a file in the current directory
#[arg(long = "log")]
pub log_to_file: bool,

Expand All @@ -48,7 +48,7 @@ pub struct CmdLineSettings {

/// Disable the Multigrid extension (disables smooth scrolling, window animations, and floating blur)
#[arg(long = "no-multigrid", env = "NEOVIDE_NO_MULTIGRID", value_parser = FalseyValueParser::new())]
pub no_multi_grid: bool,
pub no_multigrid: bool,

/// Instead of spawning a child process and leaking it, be "blocking" and let the shell persist
/// as parent process
Expand Down
Loading
Loading