diff --git a/Readme.md b/Readme.md index c50c56c..087bb1c 100644 --- a/Readme.md +++ b/Readme.md @@ -59,6 +59,8 @@ Check out the other [examples](https://github.com/gyscos/Cursive/tree/master/exa _(Colors may depend on your terminal configuration.)_ +You may also have a look at the [tutorial](https://github.com/gyscos/Cursive/tree/master/doc/tutorial_1.md). + ## Goals * **Ease of use.** Simple apps should be simple. Complex apps should be manageable. diff --git a/doc/tutorial_1.md b/doc/tutorial_1.md new file mode 100644 index 0000000..02d8d82 --- /dev/null +++ b/doc/tutorial_1.md @@ -0,0 +1,162 @@ +# Starting with cursive: Basics + +## Target goal + +In this first tutorial, we'll learn the basics of cursive, +and write a very basic first application: + +```rust +extern crate cursive; + +use cursive::Cursive; +use cursive::views::TextView; + +fn main() { + let mut siv = Cursive::new(); + + siv.add_global_callback('q', |s| s.quit()); + + siv.add_layer(TextView::new("Hello cursive! Press to quit.")); + + siv.run(); +} +``` + +Run this application, and you should have something like that: +Tutorial 1 goal + +Now that you have an idea of what we'll do, let's start from scratch. + +## Project configuration + +Let's create a new project +(this is basic cargo stuff I hope you're familiar with): + +```text +% cargo new --bin cursive_example +``` + +Now, we'll add cursive to the list of dependencies in `Cargo.toml`: + +```toml +[package] +name = "cursive_example" +version = "0.1.0" + +[dependencies] +cursive = "*" +``` + +Finally, update `src/main.rs` to import it: + +```rust +extern crate cursive; + +fn main() { +} +``` + +This simple application is now ready to use cursive. So let's do just that! + +## The Cursive root + +The cursive library is configured through a main `Cursive` root. +A typical cursive application will consist of three phases, +all centered around this object: + +1. Create a `Cursive` object. +2. Configure the `Cursive` object. +3. Run the `Cursive` object. + +Of these, the configuration phase is often the largest one, +so let's skip it for now. + +In its simplest form, a cursive application is therefore: + +```rust +extern crate cursive; + +use cursive::Cursive; + +fn main() { + let mut siv = Cursive::new(); + + siv.run(); +} +``` + +It's rather easy to identify the two steps involved. + +If you run this, you'll get an empty blue terminal, with no way of properly +leaving the application (you'll have to press to kill it). + +## Interactivity + +Let's first add a way to stop the application. We want to quit when the user +presses the letter ``. + +Cursive sends an event for every user input ; most of these are just ignored +and have no effect. The `Cursive` root has a `add_global_callback` to call +a function anytime a certain event is fired. This method takes 2 arguments: +a trigger, and a callback. + +* The trigger needs to implement `Into`. In addition to + `event::Event` itself, this includes `event::Key`, or simply `char`. These + will trigger when the corresponding key (or letter) is pressed. +* The callback should be a function taking a `&mut Cursive` as argument. Here, + we want to quit, so we'll use `Cursive::quit` in a closure: `|s| s.quit()`. + +In the end, we have: + +```rust +# src/main.rs + +extern crate cursive; + +fn main() { + let mut siv = Cursive::new(); + + siv.add_global_callback('q', |s| s.quit()); + + siv.run(); +} +``` + +As expected, running it show no visible change, but hitting the `` key at +least closes the application. + +## Views + +`View`s are the main components of the user interface in a cursive application. +At their core, they define what to draw in a rectangle of the terminal. For +instance, a view can print a line of text, or a checkbox, etc. + +Here, we'll be using a `TextView` to show a short message. `TextView` itself +can also deal with long text and do proper word-wrapping, but we won't need +that today. + +The `TextView` constructor just takes the text to use: `TextView::new("...")`. + +The `Cursive` root itself uses a `StackView` on the entire screen. This +`StackView` unsurprisingly stacks views in layers. It starts empty, so we'll +just need to add our `TextView` as a layer. The `Cursive::add_layer` does +exactly that. + +Once we've added this line, our first application is complete: + +```rust +extern crate cursive; + +use cursive::Cursive; +use cursive::views::TextView; + +fn main() { + let mut siv = Cursive::new(); + + siv.add_global_callback('q', |s| s.quit()); + + siv.add_layer(TextView::new("Hello cursive! Press to quit.")); + + siv.run(); +} +``` diff --git a/doc/tutorial_1.png b/doc/tutorial_1.png new file mode 100644 index 0000000..0a43584 Binary files /dev/null and b/doc/tutorial_1.png differ