Fixed broken tests, and corrected public export
This commit is contained in:
parent
805ec959c1
commit
6cdce1bc25
@ -29,6 +29,8 @@ members = [
|
||||
"crossterm_terminal",
|
||||
"crossterm_input",
|
||||
"crossterm_screen",
|
||||
"examples/program_examples/snake",
|
||||
"examples/program_examples/first_depth_search"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
@ -50,3 +52,7 @@ path = "examples/program_examples/logging.rs"
|
||||
[[example]]
|
||||
name = "command_bar"
|
||||
path = "examples/program_examples/command_bar.rs"
|
||||
|
||||
[[example]]
|
||||
name = "snake"
|
||||
path = "examples/program_examples/snake"
|
@ -1,6 +1,6 @@
|
||||
extern crate crossterm;
|
||||
|
||||
use crossterm::{cursor, input, ClearType, Crossterm, Screen, Terminal, TerminalCursor};
|
||||
use crossterm::{input, ClearType, Crossterm, Screen, Terminal, TerminalCursor, InputEvent, KeyEvent};
|
||||
|
||||
use std::io::Read;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -22,22 +22,20 @@ fn main() {
|
||||
|
||||
thread::spawn(move || {
|
||||
let input = input();
|
||||
let mut stdin = input.read_async().bytes();
|
||||
let mut stdin = input.read_async();
|
||||
|
||||
loop {
|
||||
let a = stdin.next();
|
||||
|
||||
match a {
|
||||
Some(Ok(13)) => {
|
||||
match stdin.next() {
|
||||
Some(InputEvent::Keyboard(KeyEvent::Char('\n'))) => {
|
||||
input_buf.lock().unwrap().clear();
|
||||
}
|
||||
Some(Ok(val)) => {
|
||||
input_buf.lock().unwrap().push(val as char);
|
||||
Some(InputEvent::Keyboard(KeyEvent::Char(character))) => {
|
||||
input_buf.lock().unwrap().push(character as char);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
thread::sleep(time::Duration::from_millis(100));
|
||||
thread::sleep(time::Duration::from_millis(10));
|
||||
count += 1;
|
||||
}
|
||||
})
|
||||
@ -73,7 +71,7 @@ fn log(input_buf: Arc<Mutex<String>>, screen: &Screen) -> Vec<thread::JoinHandle
|
||||
&cursor,
|
||||
term_height,
|
||||
);
|
||||
thread::sleep(time::Duration::from_millis(300));
|
||||
thread::sleep(time::Duration::from_millis(100));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Implementation of the first depth search algorithm
|
||||
|
||||
use super::map::Map;
|
||||
use super::messages::END_MESSAGE;
|
||||
use super::variables::{Direction, Position};
|
||||
|
||||
use crossterm::{Color, Crossterm, Screen};
|
||||
@ -8,7 +8,7 @@ use crossterm::{Color, Crossterm, Screen};
|
||||
use super::rand;
|
||||
use super::rand::distributions::{IndependentSample, Range};
|
||||
|
||||
use std::io::{stdout, Write};
|
||||
use std::io::Write;
|
||||
use std::{thread, time};
|
||||
|
||||
pub struct FirstDepthSearch<'screen> {
|
||||
@ -28,7 +28,7 @@ impl<'screen> FirstDepthSearch<'screen> {
|
||||
) -> FirstDepthSearch<'screen> {
|
||||
FirstDepthSearch {
|
||||
direction: Direction::Up,
|
||||
map: map,
|
||||
map,
|
||||
stack: Vec::new(),
|
||||
root_pos: start_pos,
|
||||
is_terminated: false,
|
||||
|
@ -6,7 +6,7 @@ mod map;
|
||||
mod messages;
|
||||
mod variables;
|
||||
|
||||
use self::crossterm::{terminal, ClearType, Color, Crossterm, Screen};
|
||||
use self::crossterm::{Color, Crossterm, Screen, ClearType, InputEvent, KeyEvent};
|
||||
|
||||
use self::messages::WELCOME_MESSAGE;
|
||||
use self::variables::{Position, Size};
|
||||
@ -62,7 +62,11 @@ fn print_welcome_screen() {
|
||||
// clear the screen and print the welcome message.
|
||||
terminal.clear(ClearType::All);
|
||||
cursor.goto(0, 0);
|
||||
terminal.write(WELCOME_MESSAGE.join("\r\n"));
|
||||
|
||||
crossterm
|
||||
.style(format!("{}", messages::WELCOME_MESSAGE.join("\n\r")))
|
||||
.with(Color::Cyan)
|
||||
.paint(&screen.stdout);
|
||||
|
||||
cursor.hide();
|
||||
cursor.goto(0, 10);
|
||||
@ -71,13 +75,11 @@ fn print_welcome_screen() {
|
||||
cursor.goto(0, 11);
|
||||
terminal.write("Press `q` to abort the program");
|
||||
|
||||
let mut stdin = input.read_async().bytes();
|
||||
let mut stdin = input.read_async();
|
||||
|
||||
// print some progress example.
|
||||
for i in (1..5).rev() {
|
||||
let a = stdin.next();
|
||||
|
||||
if let Some(Ok(b'q')) = a {
|
||||
if let Some(InputEvent::Keyboard(KeyEvent::Char('q'))) = stdin.next() {
|
||||
drop(screen);
|
||||
terminal.exit();
|
||||
break;
|
||||
@ -95,3 +97,4 @@ fn print_welcome_screen() {
|
||||
thread::sleep(time::Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
use super::variables::{Cell, Position, Size};
|
||||
use crossterm::{cursor, Color, Crossterm, ObjectStyle, Screen, StyledObject};
|
||||
|
||||
use std::fmt::Display;
|
||||
use crossterm::{cursor, Color, Crossterm, Screen};
|
||||
|
||||
pub struct Map {
|
||||
pub map: Vec<Vec<Cell>>,
|
||||
@ -38,7 +36,7 @@ impl Map {
|
||||
}
|
||||
|
||||
Map {
|
||||
map: map,
|
||||
map,
|
||||
size: Size::new(map_size.width, map_size.height),
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
extern crate crossterm;
|
||||
|
||||
use self::crossterm::{terminal, ClearType};
|
||||
use self::crossterm::{Color, ObjectStyle, StyledObject};
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Direction {
|
||||
Up = 0,
|
||||
|
@ -2,10 +2,7 @@ extern crate crossterm;
|
||||
|
||||
use crossterm::Screen;
|
||||
use std::collections::VecDeque;
|
||||
use std::io::Write;
|
||||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex, mpsc::{self, Receiver, Sender}};
|
||||
use std::thread::{self, JoinHandle};
|
||||
|
||||
/// This is an que that could be shared between threads safely.
|
||||
@ -98,11 +95,6 @@ fn main() {
|
||||
|
||||
// a thread that will log all logs in the queue.
|
||||
handle_incoming_logs(more_jobs_rx.clone(), queue.clone());
|
||||
|
||||
// for handle in thread_handles
|
||||
// {
|
||||
// handle.join();
|
||||
// }
|
||||
}
|
||||
|
||||
fn handle_incoming_logs(more_jobs_rx: SyncFlagRx, queue: WorkQueue<String>) {
|
||||
|
@ -6,63 +6,55 @@ mod messages;
|
||||
mod snake;
|
||||
mod variables;
|
||||
|
||||
use self::crossterm::{input, terminal, ClearType, Color, Crossterm, Screen};
|
||||
use self::crossterm::{
|
||||
AsyncReader, ClearType, Color, Colorize, Crossterm, InputEvent, KeyEvent, Screen,
|
||||
};
|
||||
|
||||
use map::Map;
|
||||
use snake::Snake;
|
||||
use variables::{Direction, Position, Size};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::iter::Iterator;
|
||||
use std::{thread, time};
|
||||
|
||||
fn main() {
|
||||
let map_size = title_screen();
|
||||
let map_size = ask_size();
|
||||
|
||||
{
|
||||
let mut screen = Screen::new(true);
|
||||
// screen has to be in raw mode in order for the key presses not to be printed to the screen.
|
||||
let screen = Screen::new(true);
|
||||
let crossterm = Crossterm::from_screen(&screen);
|
||||
let cursor = crossterm.cursor();
|
||||
let mut input = crossterm.input();
|
||||
|
||||
cursor.hide();
|
||||
|
||||
let mut stdin = input.read_async().bytes();
|
||||
crossterm.cursor().hide();
|
||||
|
||||
// initialize free positions for the game map.
|
||||
let mut free_positions: HashMap<String, Position> =
|
||||
HashMap::with_capacity((map_size.width * map_size.height) as usize);
|
||||
|
||||
let mut map = Map::new(map_size.clone());
|
||||
// render the map
|
||||
let mut map = Map::new(map_size);
|
||||
map.render_map(&screen, &mut free_positions);
|
||||
|
||||
let mut direction = Direction::Right;
|
||||
|
||||
let mut snake = Snake::new(map_size.clone());
|
||||
let mut snake = Snake::new();
|
||||
|
||||
// remove snake coords from free positions.
|
||||
for part in snake.get_parts().iter() {
|
||||
free_positions
|
||||
.remove_entry(format!("{},{}", part.position.x, part.position.y).as_str());
|
||||
free_positions.remove_entry(format!("{},{}", part.position.x, part.position.y).as_str());
|
||||
}
|
||||
|
||||
map.spawn_food(&free_positions, &screen);
|
||||
|
||||
let mut stdin = crossterm.input().read_async();
|
||||
let mut snake_direction = Direction::Right;
|
||||
|
||||
// start the game loop; draw, move snake and spawn food.
|
||||
loop {
|
||||
thread::sleep(time::Duration::from_millis(200));
|
||||
let pressed_key = stdin.next();
|
||||
|
||||
if let Some(Ok(key)) = pressed_key {
|
||||
match key as char {
|
||||
'w' => direction = Direction::Up,
|
||||
'a' => direction = Direction::Left,
|
||||
's' => direction = Direction::Down,
|
||||
'd' => direction = Direction::Right,
|
||||
_ => {}
|
||||
}
|
||||
if let Some(new_direction) = update_direction(&mut stdin) {
|
||||
snake_direction = new_direction;
|
||||
}
|
||||
|
||||
snake.move_snake(&direction, &screen, &mut free_positions);
|
||||
snake.move_snake(&snake_direction, &screen, &mut free_positions);
|
||||
|
||||
if map.is_out_of_bounds(snake.snake_parts[0].position) {
|
||||
break;
|
||||
@ -73,55 +65,74 @@ fn main() {
|
||||
if snake.has_eaten_food(map.foot_pos) {
|
||||
map.spawn_food(&free_positions, &screen);
|
||||
}
|
||||
}
|
||||
drop(screen);
|
||||
}
|
||||
|
||||
thread::sleep(time::Duration::from_millis(400));
|
||||
}
|
||||
game_over_screen();
|
||||
}
|
||||
|
||||
fn title_screen() -> Size {
|
||||
fn update_direction(reader: &mut AsyncReader) -> Option<Direction> {
|
||||
let pressed_key = reader.next();
|
||||
|
||||
if let Some(InputEvent::Keyboard(KeyEvent::Char(character))) = pressed_key {
|
||||
return Some(match character {
|
||||
'w' => Direction::Up,
|
||||
'a' => Direction::Left,
|
||||
's' => Direction::Down,
|
||||
'd' => Direction::Right,
|
||||
_ => return None,
|
||||
});
|
||||
} else if let Some(InputEvent::Keyboard(key)) = pressed_key {
|
||||
return Some(match key {
|
||||
KeyEvent::Up => Direction::Up,
|
||||
KeyEvent::Left => Direction::Left,
|
||||
KeyEvent::Down => Direction::Down,
|
||||
KeyEvent::Right => Direction::Right,
|
||||
_ => return None,
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn ask_size() -> Size {
|
||||
let crossterm = Crossterm::new();
|
||||
crossterm.terminal().clear(ClearType::All);
|
||||
|
||||
let cursor = crossterm.cursor();
|
||||
let terminal = crossterm.terminal().clear(ClearType::All);
|
||||
|
||||
println!("{}", messages::SNAKERS.join("\n\r"));
|
||||
println!(
|
||||
"{}",
|
||||
crossterm
|
||||
.style(format!("{}", messages::END_MESSAGE.join("\n\r")))
|
||||
.with(Color::Cyan)
|
||||
);
|
||||
|
||||
// read width
|
||||
cursor.goto(0, 15);
|
||||
println!("Enter map width:");
|
||||
println!("{}", "Enter map width:".green().on_yellow());
|
||||
cursor.goto(17, 15);
|
||||
|
||||
// read height
|
||||
let width = crossterm.input().read_line().unwrap();
|
||||
println!("\r\nEnter map height:");
|
||||
println!("{}", "\r\nEnter map height:".green().on_yellow());
|
||||
cursor.goto(17, 17);
|
||||
|
||||
let height = crossterm.input().read_line().unwrap();
|
||||
|
||||
// parse input
|
||||
let parsed_width = width.parse::<usize>().unwrap();
|
||||
let parsed_height = height.parse::<usize>().unwrap();
|
||||
|
||||
let terminal = crossterm.terminal().clear(ClearType::All);
|
||||
crossterm.terminal().clear(ClearType::All);
|
||||
|
||||
return Size::new(parsed_width, parsed_height);
|
||||
}
|
||||
|
||||
fn print_game_stats(map_size: Size, snake_lenght: usize, food_aten: usize, screen: &mut Screen) {
|
||||
let crossterm = Crossterm::new();
|
||||
|
||||
let cursor = crossterm.cursor();
|
||||
let terminal = crossterm.terminal().clear(ClearType::All);
|
||||
|
||||
screen.write(format!("Snake Lenght: {}\n\r", snake_lenght).as_ref());
|
||||
screen.write(format!("Food aten: {}\n\r", snake_lenght).as_ref());
|
||||
|
||||
cursor.goto(0, map_size.height as u16);
|
||||
cursor.goto(0, map_size.height as u16);
|
||||
}
|
||||
|
||||
fn game_over_screen() {
|
||||
let crossterm = Crossterm::new();
|
||||
|
||||
let cursor = crossterm.cursor();
|
||||
let terminal = crossterm.terminal();
|
||||
|
||||
terminal.clear(ClearType::All);
|
||||
crossterm.terminal().clear(ClearType::All);
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
@ -129,6 +140,6 @@ fn game_over_screen() {
|
||||
.style(format!("{}", messages::END_MESSAGE.join("\n\r")))
|
||||
.with(Color::Red)
|
||||
);
|
||||
// cursor.goto()
|
||||
cursor.show();
|
||||
|
||||
crossterm.cursor().show();
|
||||
}
|
||||
|
@ -1,16 +1,10 @@
|
||||
use super::snake::Snake;
|
||||
use super::variables::{Direction, Position, Size};
|
||||
use super::variables::{Position, Size};
|
||||
|
||||
use crossterm::{
|
||||
style, Color, ColorType, Crossterm, ObjectStyle, Screen, StyledObject, TerminalCursor,
|
||||
};
|
||||
use crossterm::{style, Color, Colorize, Crossterm, Screen, TerminalCursor};
|
||||
|
||||
use rand::distributions::{IndependentSample, Range};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
|
||||
use rand;
|
||||
|
||||
@ -30,14 +24,14 @@ impl Map {
|
||||
// render the map on the screen.
|
||||
pub fn render_map(&mut self, screen: &Screen, free_positions: &mut HashMap<String, Position>) {
|
||||
let crossterm = Crossterm::from_screen(screen);
|
||||
let mut cursor = crossterm.cursor();
|
||||
let mut terminal = crossterm.terminal();
|
||||
let cursor = crossterm.cursor();
|
||||
let terminal = crossterm.terminal();
|
||||
|
||||
for y in 0..self.size.height {
|
||||
for x in 0..self.size.height {
|
||||
if (y == 0 || y == self.size.height - 1) || (x == 0 || x == self.size.width - 1) {
|
||||
cursor.goto(x as u16, y as u16);
|
||||
terminal.write("█");
|
||||
"█".magenta().paint(&screen.stdout);
|
||||
} else {
|
||||
free_positions.insert(format!("{},{}", x, y), Position::new(x, y));
|
||||
}
|
||||
@ -68,7 +62,6 @@ impl Map {
|
||||
fn draw_food(&self, screen: &Screen) {
|
||||
let cursor = TerminalCursor::from_output(&screen.stdout);
|
||||
cursor.goto(self.foot_pos.x as u16, self.foot_pos.y as u16);
|
||||
style("$").with(Color::Green).paint(&screen.stdout);
|
||||
screen.stdout.flush();
|
||||
"$".green().paint(&screen.stdout);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::variables::{Direction, Position, Size};
|
||||
use crossterm::{Color, Crossterm, Screen};
|
||||
use crossterm::{Crossterm, Screen};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -18,16 +18,14 @@ impl Part {
|
||||
pub struct Snake {
|
||||
pub snake_parts: Vec<Part>,
|
||||
pub parent_pos: Position,
|
||||
map_size: Size,
|
||||
}
|
||||
|
||||
impl Snake {
|
||||
pub fn new(map_size: Size) -> Snake {
|
||||
return Snake {
|
||||
map_size,
|
||||
pub fn new() -> Snake {
|
||||
Snake {
|
||||
snake_parts: vec![Part::new(9, 10), Part::new(8, 10)],
|
||||
parent_pos: Position::new(0, 0),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_snake(
|
||||
@ -41,7 +39,6 @@ impl Snake {
|
||||
let terminal = crossterm.terminal();
|
||||
|
||||
let count = self.snake_parts.len();
|
||||
let is_food_eaten = false;
|
||||
|
||||
for (index, ref mut snake_part) in self.snake_parts.iter_mut().enumerate() {
|
||||
if index == count - 1 {
|
||||
@ -74,7 +71,7 @@ impl Snake {
|
||||
}
|
||||
|
||||
pub fn draw_snake(&mut self, screen: &Screen) {
|
||||
for (index, ref mut snake_part) in self.snake_parts.iter_mut().enumerate() {
|
||||
for snake_part in self.snake_parts.iter_mut() {
|
||||
snake_part.position.draw("■", screen);
|
||||
}
|
||||
}
|
||||
@ -94,9 +91,3 @@ impl Snake {
|
||||
return &self.snake_parts;
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SnakeState {
|
||||
MovedOutMap,
|
||||
Moved,
|
||||
AteFood,
|
||||
}
|
||||
|
@ -1,11 +1,6 @@
|
||||
extern crate crossterm;
|
||||
|
||||
use self::crossterm::{
|
||||
cursor, style, ClearType, Color, Crossterm, ObjectStyle, Screen, StyledObject, TerminalCursor,
|
||||
};
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use self::crossterm::{style, Color, Crossterm, Screen, TerminalCursor};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Direction {
|
||||
|
@ -17,7 +17,9 @@ mod crossterm;
|
||||
#[cfg(feature = "cursor")]
|
||||
pub use self::crossterm_cursor::{cursor, TerminalCursor};
|
||||
#[cfg(feature = "input")]
|
||||
pub use self::crossterm_input::{input, AsyncReader, KeyEvent, TerminalInput};
|
||||
pub use self::crossterm_input::{
|
||||
input, AsyncReader, InputEvent, KeyEvent, MouseButton, MouseEvent, SyncReader, TerminalInput,
|
||||
};
|
||||
#[cfg(feature = "screen")]
|
||||
pub use self::crossterm_screen::{AlternateScreen, Screen};
|
||||
#[cfg(feature = "style")]
|
||||
|
Loading…
Reference in New Issue
Block a user