From 207e7e0b525f5704ea3e5954fa001c3ce611b6af Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Mon, 15 Aug 2016 17:26:44 -0700 Subject: [PATCH] Add first tutorial --- Readme.md | 2 + doc/tutorial_1.md | 162 +++++++++++++++++++++++++++++++++++++++++++++ doc/tutorial_1.png | Bin 0 -> 2804 bytes 3 files changed, 164 insertions(+) create mode 100644 doc/tutorial_1.md create mode 100644 doc/tutorial_1.png 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 0000000000000000000000000000000000000000..0a43584cbe5cad360afdb1168d62bb01c94f6d92 GIT binary patch literal 2804 zcmd5;c~H~W7XG1@9koR^0jcu<3xOh=s1Z;E6(JOqm|g>beJ24x;IyzH-(z;QJBJT~w=6E30z13wSra~u?-99s#W4^7#3XmO z0D!^D@|{9K<`6TXDdEF_%xQF3N)P~ues6Ai!8UAkWgPirI9QejfF ze?~nkIC|;=@?>1vEMgLTfU)>?WMs;S6V<}pjN6z5fw*Y4*VOpEP`H?`(e<)St2K zEyYjSDh~WJ&ON5fFXbmy`;_uS4L^tNFQ@ylzyI!N^!tKpm8tWHsl{)l1u)O2Ys)Hy z^_&Q;1Glo*>(WAbUVRm)vkv91=UWH%P281-OS;s-!|e$!6ASK|gUwGZ+>Pf#4%`f< z6XaI67~uJ`k~D+0&K8@ zn&ru4jZ$iw8=}qxQ$r z`W=vH<#6|n%5`JJh>>%ZbFjKkMuQgTR*|do)_L~w6v;bajDJIh(`$8chAvl@OgGu|Q07QvoC#yw&>96fVZyjt}1tPYxFj%g)ah3C-2I^tkx7g*BO~=Sy+ft_`c0GiUCwx#t?z^2YrmrRt^Z zZ5&hD$r_MUjc}+Jsib5C?^9De3h`la`#=G|h~V{4x0txA>1~>HiVDK|L5^UUX}+Cp z?#%t+0IH3h9PgJOmAfIc%svF#cK$6IJztS1LkS;SJs~|`^P=e5y*8grdz+MM)}`AP z{U8aKlu>QMcE<=M(%uu>o`~0;eTeGPRK_G6YA$5NJ#{s%J-Y*kTho>c7^$gEQKcTP zQHElSHz^^dS9NaQC1dp?eQlCB?Z1L_VBO z5YV>tonv4^i5=AbSf=g4UZ0)ij6q}BoNCEfkF6q^O^y*r&x-%%O?=h7vZO$CJTbTd zo`gOkj4@QCKCL7|AgOFGv_!bp9kYZy)mYl9A5-~_HQ6Ua^))6} I|;k;uDtwas7 z26G||LJ9Jjh4B-l`X!mX&<3&V8(n2b6?zMujWT>D{WBzBjp=qv)Hw?2vUC&F{8h!p z*rvq3TQmnxjTqVlB{*|~x;Vyu=c+SYorXY{AAD*Q-0#mXvLVQNL5j z-tfWsQYzeg5V>$hu5WQ^_p2O8kM_J_{Lx;SZHb<-LNq?)*QEwzSSZ($XB+8S^V?AF z_Hg7X^vvSykkH8`H$i(6Z$d`6YYtnVVfOC;yA^6x<>SC7}-8y$&YrH0qBo7-M* z^S}+xBC>jw>K-@)9Vde%>WXL^E-?WU;NBroXDE-ir6vE3)I*8wIHHeoQcdbxEe7L@ zIu|JZ+kx2?Sc7fO8T#6w`7yFXhox2JvjY0q+vhgd;MNC?me+6S`PnxqeFNq-FP&2t zTqkE-gwDlQozVC04>>oL(|94Qvh9bzG$rj4njGImUvews_nWhTui@9Fu)zi8z z3-`$mBnEYBLU8V7tQItGzv}HJ4m08#PRYP&v6ZSv>|R`lh^CGCriBNrN?hSel%$qW z5AX3y)LE;RAJDWuP32u-CLYn8KlPYuSPrgD_8daJ4~sL4h8A%0sxStyXyTvR<+&O_NI~l{i)~wYz%l~%ozXD{^5NphCiPI=4Mu= J1QWOW{{Xm?8&CiM literal 0 HcmV?d00001