Skip to content

Commit

Permalink
Merge branch 'main' into fsundvik/text-gamma
Browse files Browse the repository at this point in the history
  • Loading branch information
Kethku authored May 11, 2024
2 parents ec54e0d + f5bab65 commit fe6ade1
Show file tree
Hide file tree
Showing 25 changed files with 217 additions and 204 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,11 @@ jobs:
with:
neovim: true

- name: Install Cargo Binstall
uses: cargo-bins/cargo-binstall@main

- name: Install cargo-nextest
uses: taiki-e/install-action@nextest
run: cargo binstall -y cargo-nextest

- name: Test
env:
Expand All @@ -90,8 +93,6 @@ jobs:
path: |
test-results-${{ matrix.os }}-${{ matrix.toolchain }}
- name: Install Cargo Binstall
uses: cargo-bins/cargo-binstall@main
- name: Install Sarif
run: cargo binstall -y clippy-sarif sarif-fmt
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:

steps:
- name: Download HTML
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: book
path: ./book
Expand Down Expand Up @@ -119,7 +119,7 @@ jobs:

steps:
- name: Download HTML & Sitemap
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4

- name: Move Sitemap Into HTML
run: mv ./sitemap/sitemap.xml ./book/html
Expand Down
4 changes: 2 additions & 2 deletions src/bridge/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub enum GuiOption {
GuiFont(String),
GuiFontSet(String),
GuiFontWide(String),
LineSpace(i64),
LineSpace(f64),
Pumblend(u64),
ShowTabLine(u64),
TermGuiColors(bool),
Expand Down Expand Up @@ -454,7 +454,7 @@ fn parse_option_set(option_set_arguments: Vec<Value>) -> Result<RedrawEvent> {
"guifont" => GuiOption::GuiFont(parse_string(value)?),
"guifontset" => GuiOption::GuiFontSet(parse_string(value)?),
"guifontwide" => GuiOption::GuiFontWide(parse_string(value)?),
"linespace" => GuiOption::LineSpace(parse_i64(value)?),
"linespace" => GuiOption::LineSpace(parse_f64(value)?),
"pumblend" => GuiOption::Pumblend(parse_u64(value)?),
"showtabline" => GuiOption::ShowTabLine(parse_u64(value)?),
"termguicolors" => GuiOption::TermGuiColors(parse_bool(value)?),
Expand Down
69 changes: 40 additions & 29 deletions src/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ mod ui_commands;

use anyhow::{bail, Context, Result};
use itertools::Itertools;
use log::{error, info};
use log::info;
use nvim_rs::{error::CallError, Neovim, UiAttachOptions, Value};
use rmpv::Utf8String;
use std::{io::Error, ops::Add};
use tokio::runtime::{Builder, Runtime};
use std::{io::Error, ops::Add, time::Duration};
use tokio::{
runtime::{Builder, Runtime},
select,
time::timeout,
};
use winit::event_loop::EventLoopProxy;

use crate::{
cmd_line::CmdLineSettings, editor::start_editor, running_tracker::*, settings::*,
units::GridSize, window::UserEvent,
cmd_line::CmdLineSettings, editor::start_editor, settings::*, units::GridSize,
window::UserEvent,
};
pub use handler::NeovimHandler;
use session::{NeovimInstance, NeovimSession};
Expand All @@ -34,7 +38,7 @@ const INTRO_MESSAGE_LUA: &str = include_str!("../../lua/intro.lua");
const NEOVIM_REQUIRED_VERSION: &str = "0.9.2";

pub struct NeovimRuntime {
runtime: Option<Runtime>,
runtime: Runtime,
}

fn neovim_instance() -> Result<NeovimInstance> {
Expand Down Expand Up @@ -134,43 +138,50 @@ async fn launch(handler: NeovimHandler, grid_size: Option<GridSize<u32>>) -> Res
res.map(|()| session)
}

async fn run(session: NeovimSession) {
match session.io_handle.await {
Err(join_error) => error!("Error joining IO loop: '{}'", join_error),
Ok(Err(error)) => {
if !error.is_channel_closed() {
error!("Error: '{}'", error);
async fn run(session: NeovimSession, proxy: EventLoopProxy<UserEvent>) {
let mut session = session;

if let Some(process) = session.neovim_process.as_mut() {
// We primarily wait for the stdio to finish, but due to bugs,
// for example, this one in in Neovim 0.9.5
// https://github.com/neovim/neovim/issues/26743
// it does not always finish.
// So wait for some additional time, both to make the bug obvious and to prevent incomplete
// data.
select! {
_ = &mut session.io_handle => {}
_ = process.wait() => {
log::info!("The Neovim process quit before the IO stream, waiting two seconds");
if timeout(Duration::from_millis(2000), session.io_handle)
.await
.is_err()
{
log::info!("The IO stream was never closed, forcing Neovide to exit");
}
}
}
Ok(Ok(())) => {}
};
RUNNING_TRACKER.quit("neovim processed failed");
};
} else {
session.io_handle.await.ok();
}
log::info!("Neovim has quit");
proxy.send_event(UserEvent::NeovimExited).ok();
}

impl NeovimRuntime {
pub fn new() -> Result<Self, Error> {
let runtime = Builder::new_multi_thread().enable_all().build()?;

Ok(Self {
runtime: Some(runtime),
})
Ok(Self { runtime })
}

pub fn launch(
&mut self,
event_loop_proxy: EventLoopProxy<UserEvent>,
grid_size: Option<GridSize<u32>>,
) -> Result<()> {
let handler = start_editor(event_loop_proxy);
let runtime = self.runtime.as_ref().unwrap();
let session = runtime.block_on(launch(handler, grid_size))?;
runtime.spawn(run(session));
let handler = start_editor(event_loop_proxy.clone());
let session = self.runtime.block_on(launch(handler, grid_size))?;
self.runtime.spawn(run(session, event_loop_proxy));
Ok(())
}
}

impl Drop for NeovimRuntime {
fn drop(&mut self) {
self.runtime.take().unwrap().shutdown_background();
}
}
21 changes: 14 additions & 7 deletions src/bridge/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use nvim_rs::{error::LoopError, neovim::Neovim, Handler};
use tokio::{
io::{split, AsyncRead, AsyncWrite},
net::TcpStream,
process::Command,
process::{Child, Command},
spawn,
task::JoinHandle,
};
Expand All @@ -26,6 +26,7 @@ type BoxedWriter = Box<dyn AsyncWrite + Send + Unpin + 'static>;
pub struct NeovimSession {
pub neovim: Neovim<NeovimWriter>,
pub io_handle: JoinHandle<std::result::Result<(), Box<LoopError>>>,
pub neovim_process: Option<Child>,
}

#[cfg(debug_assertions)]
Expand All @@ -42,12 +43,16 @@ impl NeovimSession {
instance: NeovimInstance,
handler: impl Handler<Writer = NeovimWriter>,
) -> Result<Self> {
let (reader, writer) = instance.connect().await?;
let (reader, writer, neovim_process) = instance.connect().await?;
let (neovim, io) =
Neovim::<NeovimWriter>::new(reader.compat(), Box::new(writer.compat_write()), handler);
let io_handle = spawn(io);

Ok(Self { neovim, io_handle })
Ok(Self {
neovim,
io_handle,
neovim_process,
})
}
}

Expand All @@ -66,14 +71,16 @@ pub enum NeovimInstance {
}

impl NeovimInstance {
async fn connect(self) -> Result<(BoxedReader, BoxedWriter)> {
async fn connect(self) -> Result<(BoxedReader, BoxedWriter, Option<Child>)> {
match self {
NeovimInstance::Embedded(cmd) => Self::spawn_process(cmd).await,
NeovimInstance::Server { address } => Self::connect_to_server(address).await,
NeovimInstance::Server { address } => Self::connect_to_server(address)
.await
.map(|(reader, writer)| (reader, writer, None)),
}
}

async fn spawn_process(mut cmd: Command) -> Result<(BoxedReader, BoxedWriter)> {
async fn spawn_process(mut cmd: Command) -> Result<(BoxedReader, BoxedWriter, Option<Child>)> {
let mut child = cmd.stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
let reader = Box::new(
child
Expand All @@ -88,7 +95,7 @@ impl NeovimInstance {
.ok_or_else(|| Error::new(ErrorKind::Other, "Can't open stdin"))?,
);

Ok((reader, writer))
Ok((reader, writer, Some(child)))
}

async fn connect_to_server(address: String) -> Result<(BoxedReader, BoxedWriter)> {
Expand Down
48 changes: 17 additions & 31 deletions src/bridge/ui_commands.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
use std::sync::Mutex;
use std::sync::OnceLock;

use log::trace;

use anyhow::{Context, Result};
use nvim_rs::{call_args, error::CallError, rpc::model::IntoVal, Neovim, Value};
use strum::AsRefStr;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
use tokio::sync::mpsc::unbounded_channel;

use super::show_error_message;
use crate::{
bridge::{ApiInformation, NeovimWriter},
profiling::{tracy_dynamic_zone, tracy_fiber_enter, tracy_fiber_leave},
running_tracker::RUNNING_TRACKER,
LoggingSender,
};

Expand Down Expand Up @@ -271,31 +270,17 @@ impl AsRef<str> for UiCommand {
}
}

struct UIChannels {
sender: LoggingSender<UiCommand>,
receiver: Mutex<Option<UnboundedReceiver<UiCommand>>>,
}

impl UIChannels {
fn new() -> Self {
let (sender, receiver) = unbounded_channel();
Self {
sender: LoggingSender::attach(sender, "UICommand"),
receiver: Mutex::new(Some(receiver)),
}
}
}

lazy_static! {
static ref UI_CHANNELS: UIChannels = UIChannels::new();
}
static UI_COMMAND_CHANNEL: OnceLock<LoggingSender<UiCommand>> = OnceLock::new();

pub fn start_ui_command_handler(nvim: Neovim<NeovimWriter>, api_information: &ApiInformation) {
let (serial_tx, mut serial_rx) = unbounded_channel::<SerialCommand>();
let ui_command_nvim = nvim.clone();
let (sender, mut ui_command_receiver) = unbounded_channel();
UI_COMMAND_CHANNEL
.set(LoggingSender::attach(sender, "UIComand"))
.expect("The UI command channel is already created");
tokio::spawn(async move {
let mut ui_command_receiver = UI_CHANNELS.receiver.lock().unwrap().take().unwrap();
while RUNNING_TRACKER.is_running() {
loop {
match ui_command_receiver.recv().await {
Some(UiCommand::Serial(serial_command)) => {
tracy_dynamic_zone!(serial_command.as_ref());
Expand All @@ -309,18 +294,17 @@ pub fn start_ui_command_handler(nvim: Neovim<NeovimWriter>, api_information: &Ap
parallel_command.execute(&ui_command_nvim).await;
});
}
None => {
RUNNING_TRACKER.quit("ui command channel failed");
}
None => break,
}
}
log::info!("ui command receiver finished");
});

let has_x_buttons = api_information.version.has_version(0, 10, 0);

tokio::spawn(async move {
tracy_fiber_enter!("Serial command");
while RUNNING_TRACKER.is_running() {
loop {
tracy_fiber_leave();
let res = serial_rx.recv().await;
tracy_fiber_enter!("Serial command");
Expand All @@ -331,11 +315,10 @@ pub fn start_ui_command_handler(nvim: Neovim<NeovimWriter>, api_information: &Ap
serial_command.execute(&nvim, has_x_buttons).await;
tracy_fiber_enter!("Serial command");
}
None => {
RUNNING_TRACKER.quit("serial ui command channel failed");
}
None => break,
}
}
log::info!("serial command receiver finished");
});
}

Expand All @@ -344,5 +327,8 @@ where
T: Into<UiCommand>,
{
let command: UiCommand = command.into();
let _ = UI_CHANNELS.sender.send(command);
let _ = UI_COMMAND_CHANNEL
.get()
.expect("The UI command channel has not been initialized")
.send(command);
}
2 changes: 1 addition & 1 deletion src/channel_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tokio::sync::mpsc::{error::SendError as TokioSendError, UnboundedSender};

use crate::profiling::tracy_dynamic_zone;

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct LoggingSender<T>
where
T: Debug + AsRef<str>,
Expand Down
11 changes: 1 addition & 10 deletions src/cmd_line.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{iter, mem};

use crate::utils::is_tty;
use crate::{dimensions::Dimensions, frame::Frame, settings::*};

use anyhow::Result;
Expand All @@ -24,14 +23,6 @@ fn get_styles() -> Styles {
.placeholder(styling::AnsiColor::Cyan.on_default())
}

fn is_tty_str() -> &'static str {
if is_tty() {
"1"
} else {
"0"
}
}

#[derive(Clone, Debug, Parser)]
#[command(version, about, long_about = None, styles = get_styles())]
pub struct CmdLineSettings {
Expand Down Expand Up @@ -77,7 +68,7 @@ pub struct CmdLineSettings {
pub title_hidden: bool,

/// Spawn a child process and leak it [DEFAULT]
#[arg(long = "fork", env = "NEOVIDE_FORK", action = ArgAction::SetTrue, default_value = is_tty_str(), value_parser = FalseyValueParser::new())]
#[arg(long = "fork", env = "NEOVIDE_FORK", action = ArgAction::SetTrue, default_value = "0", value_parser = FalseyValueParser::new())]
pub fork: bool,

/// Be "blocking" and let the shell persist as parent process. Takes precedence over `--fork`.
Expand Down
2 changes: 1 addition & 1 deletion src/editor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ impl Editor {
}
GuiOption::LineSpace(linespace) => {
self.draw_command_batcher
.queue(DrawCommand::LineSpaceChanged(linespace));
.queue(DrawCommand::LineSpaceChanged(linespace as f32));

self.redraw_screen();
}
Expand Down
Loading

0 comments on commit fe6ade1

Please sign in to comment.