Skip to content

Commit

Permalink
Migrate from Termion to Crossterm
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentFoulon80 committed May 23, 2020
1 parent 108e1d7 commit a79f077
Show file tree
Hide file tree
Showing 17 changed files with 482 additions and 590 deletions.
7 changes: 2 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "console_engine"
description = "A simple console framework that provides display and input features"
version = "0.7.0"
version = "1.0.0"
authors = ["Vincent Foulon <[email protected]>"]
repository = "https://github.com/VincentFoulon80/console_engine"
readme = "README.md"
Expand All @@ -12,10 +12,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
termion = "1.5.5"
# for windows support, uncomment this :
# termion = { git = "https://gitlab.redox-os.org/Jezza/termion", branch = "windows-support", package = "termion"}

crossterm = "0.17.4"

[dev-dependencies]
rand = "0.7.3"
34 changes: 15 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,33 @@

[Changelog](https://github.com/VincentFoulon80/console_engine/releases)

**There was a huge internal change between versions 0.x and 1.x. See the [Upgrade Guide](https://github.com/VincentFoulon80/console_engine/blob/master/UPGRADE_1.0.md) to migrate your code. There's not much to change on your side !**

This library provides simple features for handling user's input and display for terminal applications.
Besides the user input and display, this library also provides some tools to build standalone "screens" that can be used as simply as printing it.

It uses [Termion](https://crates.io/crates/termion) as main tool for handling the screen and inputs. You don't have to worry about initalizing anything because the lib will handle this for you.
It uses [Crossterm](https://crates.io/crates/crossterm) as main tool for handling the screen and inputs. You don't have to worry about initalizing anything because the lib will handle this for you.

## Features

- Build custom terminal display using shapes or text
- Terminal handling with a target frame per seconds
- Keyboard and mouse support
- Terminal resizing support
- You are not interested by keyboard/mouse handling, even terminal handling ? You can still build "screens" to just draw using `println!()`
- You are not interested by keyboard/mouse handling, even terminal handling ? You can still build "screens" that will just print its content.
- Embedding screens to one another

## Platforms

Works for Linux and possibly Mac (need confirmation).

Windows support will be available as soon as termion will support it [See here for more info](https://gitlab.redox-os.org/redox-os/termion/-/merge_requests/151)
For now, you can change the cargo.toml termion dependency by this :
```toml
termion = { git = "https://gitlab.redox-os.org/Jezza/termion", branch = "windows-support", package = "termion"}
```
Note: window's input initialization requires the user to first press enter. ConsoleEngine will ask the user to press Enter while inializing.
Since it uses `crossterm`, it should work on Windows, Linux and possibly Mac (see [Tested Terminals on Crossterm's page](https://crates.io/crates/crossterm#tested-terminals)).

# example usage

## ConsoleEngine (managing input & output)
```rust
use console_engine::pixel;
use console_engine::termion::color;
use console_engine::termion::event::Key;
use console_engine::Color;
use console_engine::KeyCode;

fn main() {
// initializes a screen of 20x10 characters with a target of 3 frames per second
Expand All @@ -45,11 +41,11 @@ fn main() {
engine.clear_screen(); // reset the screen

engine.line(0, 0, 19, 9, pixel::pxl('#')); // draw a line of '#' from [0,0] to [19,9]
engine.print(0, 4, format!("Result: {}", value)); // prints some value at [0,4]
engine.print(0, 4, format!("Result: {}", value).as_str()); // prints some value at [0,4]

engine.set_pxl(4, 0, pixel::pxl_fg('O', color::Cyan)); // write a majestic cyan 'O' at [4,0]
engine.set_pxl(4, 0, pixel::pxl_fg('O', Color::Cyan)); // write a majestic cyan 'O' at [4,0]

if engine.is_key_pressed(Key::Char('q')) { // if the user presses 'q' :
if engine.is_key_pressed(KeyCode::Char('q')) { // if the user presses 'q' :
break; // exits app
}

Expand All @@ -60,18 +56,18 @@ fn main() {

## Screens (generating output)
```rust
use console_engine::screen;
use console_engine::screen::Screen;
use console_engine::pixel;

fn main() {
// create a screen of 20x11 characters
let mut scr = screen::Screen::new(20,11);
let mut scr = Screen::new(20,11);

// draw some shapes and prints some text
scr.rect(0,0, 19,10,pixel::pxl('#'));
scr.fill_circle(5,5, 3, pixel::pxl('*'));
scr.print(11,4, String::from("Hello,"));
scr.print(11,5, String::from("World!"));
scr.print(11,4, "Hello,");
scr.print(11,5, "World!");

// print the screen to the terminal
println!("{}", scr.to_string());
Expand Down
33 changes: 33 additions & 0 deletions UPGRADE_1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Removed Deprecations

- `engine.scr_w()` : use `engine.get_width()` instead
- `engine.scr_h()` : use `engine.get_height()` instead

# From 0.7.x

- Replace :
```rust
use console_engine::termion::color;
use console_engine::termion::event::Key;
use console_engine::termion::event::MouseButton;
```
by :
```rust
use console_engine::Color;
use console_engine::KeyCode;
use console_engine::MouseButton;
```
- in your code, `Key::Char('*')` becomes `KeyCode::Char('*')`
- `color` becomes `Color`.
Be aware that the Color enum has changed so instead of "Yellow" you have "DarkYellow", and "LightYellow" now is "Yellow".
Black and White variants doesn't exist anymore because of the new "Grey" and "DarkGrey".
- `engine.get_mouse_held()` and `engine.get_mouse_released()` now require that you provide a `MouseButton` as first parameter
- `screen.to_string()` as well as `pixel.to_string()` no longer exists.
If you want to print a screen you'll now use `screen.draw()` instead.
- `pixel.colors` has been replaced by `pixel.fg` and `pixel.bg`. These two are now of type Color instead of String.

# From 0.6.x or less

- `print` and `print_fbg` now uses `&str` instead of `String` for text.
If you want to keep using Strings, you'll just need to add `.as_str()` to get it to work again
- `PubScreen` no longer exists
9 changes: 4 additions & 5 deletions examples/drag-and-drop.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use console_engine::pixel;
use console_engine::termion::event::Key;
use console_engine::termion::event::MouseButton;
use console_engine::{KeyCode, MouseButton};

fn main() {
// initializes a screen filling the terminal with a target of 30 frames per second
Expand All @@ -18,7 +17,7 @@ fn main() {
loop {
engine.wait_frame(); // wait for next frame + capture inputs
engine.check_resize(); // resize the terminal if its size has changed
if engine.is_key_pressed(Key::Char('q')) {
if engine.is_key_pressed(KeyCode::Char('q')) {
// if the user presses 'q' :
break; // exits app
}
Expand All @@ -41,7 +40,7 @@ fn main() {
}

// check if a mouse button is currently held
let mouse_pos = engine.get_mouse_held();
let mouse_pos = engine.get_mouse_held(MouseButton::Left);
if let Some(mouse_pos) = mouse_pos {
// if dragging mode is enabled, move the rectangle according to mouse's position
if dragging {
Expand All @@ -51,7 +50,7 @@ fn main() {
}

// check if the mouse has been released
let mouse_pos = engine.get_mouse_released();
let mouse_pos = engine.get_mouse_released(MouseButton::Left);
if mouse_pos.is_some() {
// disable dragging mode
dragging = false;
Expand Down
10 changes: 5 additions & 5 deletions examples/graph.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use console_engine::pixel;
use console_engine::termion::color;
use console_engine::termion::event::Key;
use console_engine::Color;
use console_engine::KeyCode;

const MAX_VALUES: usize = 64;

Expand Down Expand Up @@ -55,7 +55,7 @@ fn main() {
// and display a message when it's finished
if value_position >= MAX_VALUES {
if engine.frame_count % 10 > 5 {
engine.print_fbg(2, 3, "Press 'q' to close", color::LightYellow, color::Black);
engine.print_fbg(2, 3, "Press 'q' to close", Color::Yellow, Color::Black);
}
} else {
let value = VALUES[value_position];
Expand Down Expand Up @@ -84,13 +84,13 @@ fn main() {
2,
(value_position as f32 * step) as i32,
engine.get_height() as i32 - 1,
pixel::pxl_bg(' ', color::Blue),
pixel::pxl_bg(' ', Color::Blue),
);
}
// draw the graph
draw_graph(&mut engine, values);

if engine.is_key_pressed(Key::Char('q')) {
if engine.is_key_pressed(KeyCode::Char('q')) {
// if the user presses 'q' :
break; // exits app
}
Expand Down
15 changes: 11 additions & 4 deletions examples/lines-fps.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use console_engine::pixel;
use console_engine::termion::color;
use console_engine::termion::event::Key;
use console_engine::Color;
use console_engine::KeyCode;

// generate a random pair of u32
fn random_pos(max_x: u32, max_y: u32) -> (u32, u32) {
Expand All @@ -25,7 +25,7 @@ fn main() {
loop {
engine.wait_frame(); // wait for next frame + capture inputs
engine.check_resize(); // resize the terminal if its size has changed
if engine.is_key_pressed(Key::Char('q')) {
if engine.is_key_pressed(KeyCode::Char('q')) {
// if the user presses 'q' :
break; // exits app
}
Expand All @@ -41,7 +41,14 @@ fn main() {
pos_1.1 as i32,
pos_2.0 as i32,
pos_2.1 as i32,
pixel::pxl_fg('#', color::Rgb(pxl_c.0, pxl_c.1, pxl_c.2)),
pixel::pxl_fg(
'#',
Color::Rgb {
r: pxl_c.0,
g: pxl_c.1,
b: pxl_c.2,
},
),
);

// we keep a small space to display FPS at the top-left corner
Expand Down
15 changes: 11 additions & 4 deletions examples/lines.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use console_engine::pixel;
use console_engine::termion::color;
use console_engine::termion::event::Key;
use console_engine::Color;
use console_engine::KeyCode;

// generate a random pair of u32
fn random_pos(max_x: u32, max_y: u32) -> (u32, u32) {
Expand All @@ -23,7 +23,7 @@ fn main() {
engine.wait_frame(); // wait for next frame + capture inputs
engine.check_resize(); // resize the terminal if its size has changed
// exit check
if engine.is_key_pressed(Key::Char('q')) {
if engine.is_key_pressed(KeyCode::Char('q')) {
break;
}

Expand All @@ -40,7 +40,14 @@ fn main() {
pos_1.1 as i32,
pos_2.0 as i32,
pos_2.1 as i32,
pixel::pxl_fg('#', color::Rgb(pxl_c.0, pxl_c.1, pxl_c.2)),
pixel::pxl_fg(
'#',
Color::Rgb {
r: pxl_c.0,
g: pxl_c.1,
b: pxl_c.2,
},
),
);

engine.draw(); // draw the screen
Expand Down
10 changes: 5 additions & 5 deletions examples/mouse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use console_engine::pixel;
use console_engine::termion::event::Key;
use console_engine::termion::event::MouseButton;
use console_engine::KeyCode;
use console_engine::MouseButton;

fn main() {
// initializes a screen filling the terminal with a target of 30 frames per second
Expand All @@ -10,7 +10,7 @@ fn main() {
loop {
engine.wait_frame(); // wait for next frame + capture inputs
engine.check_resize(); // resize the terminal if its size has changed
if engine.is_key_pressed(Key::Char('q')) {
if engine.is_key_pressed(KeyCode::Char('q')) {
// if the user presses 'q' :
break; // exits app
}
Expand All @@ -22,13 +22,13 @@ fn main() {
}

// prints a 'H' where the mouse is currently held
let mouse_pos = engine.get_mouse_held();
let mouse_pos = engine.get_mouse_held(MouseButton::Left);
if let Some(mouse_pos) = mouse_pos {
engine.set_pxl(mouse_pos.0 as i32, mouse_pos.1 as i32, pixel::pxl('H'));
}

// prints a 'R' where the mouse has been released
let mouse_pos = engine.get_mouse_released();
let mouse_pos = engine.get_mouse_released(MouseButton::Left);
if let Some(mouse_pos) = mouse_pos {
engine.set_pxl(mouse_pos.0 as i32, mouse_pos.1 as i32, pixel::pxl('R'));
}
Expand Down
6 changes: 3 additions & 3 deletions examples/screen-embed.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use console_engine::pixel;
use console_engine::screen::Screen;
use console_engine::termion::color;
use console_engine::Color;

fn main() {
// create a screen of 21x12 characters
Expand All @@ -10,13 +10,13 @@ fn main() {

// create a new Screen struct and draw a square inside it
let mut my_square = Screen::new(8, 8);
my_square.rect(0, 0, 7, 7, pixel::pxl_fg('#', color::LightBlue));
my_square.rect(0, 0, 7, 7, pixel::pxl_fg('#', Color::Blue));
my_square.print(1, 1, "square");

// prints the square in the main window at a specific location
screen.print_screen(2, 2, &my_square);
screen.print_screen(11, 2, &my_square);

// print the main screen on the terminal
println!("{}", screen.to_string());
screen.draw();
}
2 changes: 1 addition & 1 deletion examples/screen-simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ fn main() {
scr.print(11, 5, "World!");

// print the screen to the terminal
println!("{}", scr.to_string());
scr.draw();
}
24 changes: 9 additions & 15 deletions examples/screen-swap.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use console_engine::pixel;
use console_engine::screen::Screen;
use console_engine::termion::color;
use console_engine::termion::event::Key;
use console_engine::Color;
use console_engine::KeyCode;

fn main() {
// initializes a screen of 30x10 characters with a target of 10 frames per second
Expand All @@ -21,17 +21,11 @@ fn main() {

// initializes screen_shapes
screen_shapes.rect(0, 0, 29, 9, pixel::pxl('+'));
screen_shapes.fill_circle(4, 4, 2, pixel::pxl_fg('0', color::LightBlue));
screen_shapes.fill_triangle(27, 2, 27, 7, 17, 7, pixel::pxl_fg('#', color::Green));
screen_shapes.fill_circle(4, 4, 2, pixel::pxl_fg('0', Color::Blue));
screen_shapes.fill_triangle(27, 2, 27, 7, 17, 7, pixel::pxl_fg('#', Color::Green));

// initializes screen_empty
screen_empty.print_fbg(
11,
9,
"It's empty, right ?",
color::LightBlack,
color::Black,
);
screen_empty.print_fbg(11, 9, "It's empty, right ?", Color::DarkGrey, Color::Black);

// set the engine's screen to help on startup
engine.set_screen(&screen_help);
Expand All @@ -41,16 +35,16 @@ fn main() {
engine.wait_frame(); // wait for next frame + capture inputs

// exit check
if engine.is_key_pressed(Key::Char('q')) {
if engine.is_key_pressed(KeyCode::Char('q')) {
break;
}

// when the corresponding key is pressed (1,2 or 3), swap to the corresponding screen
if engine.is_key_pressed(Key::Char('1')) {
if engine.is_key_pressed(KeyCode::Char('1')) {
engine.set_screen(&screen_help);
} else if engine.is_key_pressed(Key::Char('2')) {
} else if engine.is_key_pressed(KeyCode::Char('2')) {
engine.set_screen(&screen_shapes);
} else if engine.is_key_pressed(Key::Char('3')) {
} else if engine.is_key_pressed(KeyCode::Char('3')) {
engine.set_screen(&screen_empty);
}

Expand Down
Loading

0 comments on commit a79f077

Please sign in to comment.