nvim_rs/examples/
scorched_earth.rs

1//! # Scorched earth
2//!
3//! A minimal port of
4//! [scorched earth by boxofrox](https://github.com/boxofrox/neovim-scorched-earth)
5//! to nvim-rs. Works the same, but foregoes any error handling, removes the
6//! customisation of color, and removes some abstractions that aren't helpfull
7//! in an example.
8//!
9//! Note that this example uses `tokio`, while `scorched_earth_as` uses
10//! async-std.
11//!
12//! ## Usage
13//!
14//! First, build this example via
15//!
16//! ```sh
17//! cargo build --example scorched_earth
18//! ```
19//!
20//! Then follow the steps described in the [`README`](README.md) for the examples.
21//!
22//! ## Description
23//!
24//! Some overview over the code:
25//!
26//! * The associated type for our [`Handler`](crate::rpc::handler::Handler) is
27//! out stdout. But tokio's [`Stdout`](tokio::io::Stdout) does not implement
28//! [`futures::io::AsyncWrite`](futures::io::AsyncWrite), so it needs to be
29//! wrapped in the provided [`Compat`](crate::compat::tokio::Compat) type.
30//!
31//! * The handler struct `NeovimHandler` needs to contain some plugin state,
32//! namely two cursor positions `start` and `end`. It needs to be `Send` and
33//! `Sync`, and we need mutable access, so we wrap it in a `Arc<Mutex<_>>`.
34//!
35//! * Implementing the [`Handler`](crate::Handler) trait requires some magic
36//! because of the async functions, we we use the
37//! [`async_trait`](https://docs.rs/async-trait/0.1.21/async_trait/) macro.
38//!
39//! * We use `Stdout` as the type for the `Writer` because neovim acts as our
40//! parent, so it reads from our stdout. Note that this is the [async
41//! version](tokio::io::Stdout) from Tokio.
42//!
43//! * We only implement `handle_notify` since we don't want to serve requests.
44//! It gets a [`Neovim`](crate::Neovim) passed that we can use to send
45//! requests to neovim. All requests are async methods, so we need to `await`
46//! them.
47//!
48//! * The main function is denoted `#[tokio::main]` to use async notation, but
49//! it would be perfectly feasible to explicitely create a runtime and use that.
50//!
51//! * After creation of the handler, we connect to neovim via one of the
52//! [`new_*`](crate::create) functions. It gives back a
53//! [`Neovim`](crate::Neovim) instance which we could use for requests, and a
54//! handle for the io loop.
55//!
56//! * The plugin quits by ending the IO task when neovim closes the channel, so
57//!   we don't need to do anything special. Any cleanup-logic can happen after
58//!   the IO task has finished. Note that we're loosing access to our
59//!   [`Handler`](crate::Handler), so we might need to implement
60//!   [`Drop`](std::ops::Drop) for it, see the
61//!   [example](crate::examples::handler_drop).
62//!
63//! * After the IO task has finished, we're inspecting the errors to see why it
64//! went. A join error simply gets printed, then we inspect potential errors
65//! from the io loop itself. First, if we did not see a general reader error, we
66//! try to send some last notification to the neovim user. Secondly, we quietly
67//! ignore the channel being closed, because this usually means that it was
68//! closed by neovim, which isn't always an error.
69//!
70//!   *Note*: A closed channel could still mean an error, so the plugin has the
71//!   option to react to this.
72//!
73//! * As with the other examples, we implement [`Spawn`](futures::task::Spawn)
74//! for our `NeovimHandler` most trivially.