2018 edition (#222)
This commit is contained in:
parent
7cda56bc9a
commit
5494525d89
@ -29,3 +29,12 @@ script:
|
||||
- if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then cargo fmt --all -- --check; fi
|
||||
- cargo build
|
||||
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then cargo test --all -- --nocapture --test-threads 1; else cargo test --all --exclude crossterm_winapi -- --nocapture --test-threads 1; fi
|
||||
- |
|
||||
pushd examples/program_examples
|
||||
for d in */ ; do
|
||||
pushd "$d"
|
||||
cargo build
|
||||
if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then cargo fmt --all -- --check; fi
|
||||
popd
|
||||
done
|
||||
popd
|
||||
|
@ -9,6 +9,7 @@ license = "MIT"
|
||||
keywords = ["console", "color", "cursor", "input", "terminal"]
|
||||
exclude = ["target", "Cargo.lock"]
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
default = ["cursor", "style","terminal","screen","input"]
|
||||
|
@ -50,8 +50,6 @@ crossterm_cursor = "0.2"
|
||||
Import the `crossterm_cursor` modules you want to use.
|
||||
|
||||
```rust
|
||||
extern crate crossterm_cursor;
|
||||
|
||||
pub use crossterm_cursor::{cursor, TerminalCursor};
|
||||
```
|
||||
|
||||
|
@ -3,17 +3,13 @@
|
||||
//!
|
||||
#![allow(unused_must_use, dead_code)]
|
||||
|
||||
extern crate crossterm_cursor;
|
||||
|
||||
use std::io::Write;
|
||||
use std::time::Instant;
|
||||
|
||||
use crossterm_cursor::cursor;
|
||||
|
||||
use self::crossterm_cursor::{queue, Goto, Hide, Output, QueueableCommand};
|
||||
use crossterm_cursor::{cursor, queue, Goto, Hide, Output, QueueableCommand};
|
||||
|
||||
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
||||
pub fn goto() {
|
||||
fn goto() {
|
||||
// Get the cursor
|
||||
let cursor = cursor();
|
||||
// Set the cursor to position X: 10, Y: 5 in the terminal
|
||||
@ -21,7 +17,7 @@ pub fn goto() {
|
||||
}
|
||||
|
||||
/// get the cursor position
|
||||
pub fn pos() {
|
||||
fn pos() {
|
||||
// Get the cursor
|
||||
let cursor = cursor();
|
||||
// get the cursor position.
|
||||
@ -31,7 +27,7 @@ pub fn pos() {
|
||||
}
|
||||
|
||||
/// Move the cursor 3 up | demonstration.
|
||||
pub fn move_up() {
|
||||
fn move_up() {
|
||||
// Get the cursor
|
||||
let mut cursor = cursor();
|
||||
|
||||
@ -40,21 +36,21 @@ pub fn move_up() {
|
||||
}
|
||||
|
||||
/// Move the cursor 3 to the right | demonstration.
|
||||
pub fn move_right() {
|
||||
fn move_right() {
|
||||
let mut cursor = cursor();
|
||||
// Move the cursor to position 3 times to the right in the terminal
|
||||
cursor.move_right(3);
|
||||
}
|
||||
|
||||
/// Move the cursor 3 down | demonstration.
|
||||
pub fn move_down() {
|
||||
fn move_down() {
|
||||
let mut cursor = cursor();
|
||||
// Move the cursor to position 3 times to the down in the terminal
|
||||
cursor.move_down(3);
|
||||
}
|
||||
|
||||
/// Save and reset cursor position | demonstration..
|
||||
pub fn save_and_reset_position() {
|
||||
fn save_and_reset_position() {
|
||||
let cursor = cursor();
|
||||
|
||||
// Goto X: 5 Y: 5
|
||||
@ -74,19 +70,19 @@ pub fn save_and_reset_position() {
|
||||
}
|
||||
|
||||
/// Hide cursor display | demonstration.
|
||||
pub fn hide_cursor() {
|
||||
fn hide_cursor() {
|
||||
let cursor = cursor();
|
||||
cursor.hide();
|
||||
}
|
||||
|
||||
/// Show cursor display | demonstration.
|
||||
pub fn show_cursor() {
|
||||
fn show_cursor() {
|
||||
let cursor = cursor();
|
||||
cursor.show();
|
||||
}
|
||||
|
||||
/// Show cursor display, only works on certain terminals.| demonstration
|
||||
pub fn blink_cursor() {
|
||||
fn blink_cursor() {
|
||||
let cursor = cursor();
|
||||
cursor.blink(false);
|
||||
cursor.blink(false);
|
@ -3,6 +3,16 @@
|
||||
//!
|
||||
//! Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0
|
||||
|
||||
use crossterm_utils::Result;
|
||||
|
||||
use self::ansi_cursor::AnsiCursor;
|
||||
pub use self::cursor::{
|
||||
cursor, BlinkOff, BlinkOn, Down, Goto, Hide, Left, ResetPos, Right, SavePos, Show,
|
||||
TerminalCursor, Up,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use self::winapi_cursor::WinApiCursor;
|
||||
|
||||
mod cursor;
|
||||
|
||||
#[cfg(test)]
|
||||
@ -12,17 +22,6 @@ mod ansi_cursor;
|
||||
#[cfg(windows)]
|
||||
mod winapi_cursor;
|
||||
|
||||
use self::ansi_cursor::AnsiCursor;
|
||||
#[cfg(windows)]
|
||||
use self::winapi_cursor::WinApiCursor;
|
||||
|
||||
pub use self::cursor::{
|
||||
cursor, BlinkOff, BlinkOn, Down, Goto, Hide, Left, ResetPos, Right, SavePos, Show,
|
||||
TerminalCursor, Up,
|
||||
};
|
||||
|
||||
use crossterm_utils::Result;
|
||||
|
||||
///! This trait defines the actions that can be performed with the terminal cursor.
|
||||
///! This trait can be implemented so that a concrete implementation of the ITerminalCursor can fulfill
|
||||
///! the wishes to work on a specific platform.
|
@ -2,10 +2,11 @@
|
||||
//! This module is used for windows 10 terminals and UNIX terminals by default.
|
||||
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position etc.
|
||||
|
||||
use super::ITerminalCursor;
|
||||
use crossterm_utils::{csi, write_cout, Result};
|
||||
|
||||
use crate::sys::{get_cursor_position, show_cursor};
|
||||
|
||||
use crossterm_utils::{write_cout, Result};
|
||||
use super::ITerminalCursor;
|
||||
|
||||
#[inline]
|
||||
pub fn get_goto_ansi(x: u16, y: u16) -> String {
|
||||
|
@ -1,12 +1,11 @@
|
||||
//! A module that contains all the actions related to cursor movement in the terminal.
|
||||
//! Like: moving the cursor position; saving and resetting the cursor position; hiding showing and control the blinking of the cursor.
|
||||
|
||||
use super::*;
|
||||
|
||||
use crossterm_utils::{Command, Result};
|
||||
|
||||
#[cfg(windows)]
|
||||
use crossterm_utils::supports_ansi;
|
||||
use crossterm_utils::{impl_display, Command, Result};
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Allows you to preform actions with the terminal cursor.
|
||||
///
|
||||
|
@ -1,13 +1,14 @@
|
||||
#![allow(unused_must_use)]
|
||||
|
||||
use super::AnsiCursor;
|
||||
use super::ITerminalCursor;
|
||||
|
||||
/* ======================== WinApi =========================== */
|
||||
#[cfg(windows)]
|
||||
mod winapi_tests {
|
||||
|
||||
use super::super::WinApiCursor;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn goto_winapi() {
|
||||
let cursor = WinApiCursor::new();
|
||||
|
@ -2,10 +2,12 @@
|
||||
//! This module is used for Windows terminals that do not support ANSI escape codes.
|
||||
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position.
|
||||
|
||||
use super::ITerminalCursor;
|
||||
use crate::sys::winapi::{Cursor, Handle};
|
||||
use crossterm_utils::Result;
|
||||
|
||||
use crate::sys::winapi::{Cursor, Handle};
|
||||
|
||||
use super::ITerminalCursor;
|
||||
|
||||
/// This struct is a windows implementation for cursor related actions.
|
||||
pub struct WinApiCursor;
|
||||
|
||||
|
@ -1,16 +1,11 @@
|
||||
#[macro_use]
|
||||
extern crate crossterm_utils;
|
||||
|
||||
#[cfg(windows)]
|
||||
extern crate winapi;
|
||||
|
||||
mod cursor;
|
||||
pub mod sys;
|
||||
|
||||
pub use self::crossterm_utils::{
|
||||
pub use crossterm_utils::{
|
||||
execute, queue, Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result,
|
||||
};
|
||||
|
||||
pub use self::cursor::{
|
||||
cursor, BlinkOff, BlinkOn, Down, Goto, Hide, Left, ResetPos, Right, SavePos, Show,
|
||||
TerminalCursor, Up,
|
||||
};
|
||||
|
||||
mod cursor;
|
||||
pub mod sys;
|
||||
|
@ -1,15 +1,14 @@
|
||||
#[cfg(unix)]
|
||||
pub use self::unix::get_cursor_position;
|
||||
#[cfg(unix)]
|
||||
pub use self::unix::show_cursor;
|
||||
#[cfg(windows)]
|
||||
pub use self::winapi::get_cursor_position;
|
||||
#[cfg(windows)]
|
||||
pub use self::winapi::show_cursor;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub mod unix;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub mod winapi;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub use self::unix::get_cursor_position;
|
||||
#[cfg(windows)]
|
||||
pub use self::winapi::get_cursor_position;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub use self::unix::show_cursor;
|
||||
#[cfg(windows)]
|
||||
pub use self::winapi::show_cursor;
|
@ -1,9 +1,11 @@
|
||||
use crossterm_utils::{
|
||||
sys::unix::{self, RAW_MODE_ENABLED},
|
||||
Result,
|
||||
};
|
||||
use std::io::{self, BufRead, Write};
|
||||
|
||||
use crossterm_utils::{
|
||||
csi,
|
||||
sys::unix::{self, RAW_MODE_ENABLED},
|
||||
write_cout, Result,
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn get_cursor_position() -> (u16, u16) {
|
||||
if unsafe { RAW_MODE_ENABLED } {
|
||||
|
@ -52,8 +52,6 @@ crossterm_input = "0.3"
|
||||
Import the `crossterm_input` modules you want to use.
|
||||
|
||||
```rust
|
||||
extern crate crossterm_input;
|
||||
|
||||
pub use crossterm_input::{input, AsyncReader, InputEvent, KeyEvent, MouseButton, MouseEvent, SyncReader, TerminalInput};
|
||||
```
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
extern crate crossterm_input;
|
||||
use crossterm_input::input;
|
||||
|
||||
use self::crossterm_input::input;
|
||||
|
||||
pub fn read_char() {
|
||||
fn read_char() {
|
||||
let input = input();
|
||||
|
||||
match input.read_char() {
|
||||
@ -11,7 +9,7 @@ pub fn read_char() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_line() {
|
||||
fn read_line() {
|
||||
let input = input();
|
||||
|
||||
match input.read_line() {
|
@ -1,8 +1,8 @@
|
||||
extern crate crossterm_input;
|
||||
extern crate crossterm_screen;
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
use crossterm_input::{input, InputEvent, KeyEvent, MouseButton, MouseEvent, RawScreen};
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
fn process_input_event(key_event: InputEvent) -> bool {
|
||||
match key_event {
|
||||
@ -76,7 +76,7 @@ fn process_input_event(key_event: InputEvent) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn read_asynchronously() {
|
||||
fn read_asynchronously() {
|
||||
// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
|
||||
if let Ok(_raw) = RawScreen::into_raw_mode() {
|
||||
let input = input();
|
||||
@ -100,7 +100,7 @@ pub fn read_asynchronously() {
|
||||
} // <=== raw modes will be disabled here
|
||||
} // <=== background reader will be disposed when dropped.
|
||||
|
||||
pub fn read_synchronously() {
|
||||
fn read_synchronously() {
|
||||
// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
|
||||
if let Ok(_raw) = RawScreen::into_raw_mode() {
|
||||
let input = input();
|
@ -1,20 +1,24 @@
|
||||
//! A module that contains all the actions related to reading input from the terminal.
|
||||
//! Like reading a line, reading a character and reading asynchronously.
|
||||
|
||||
mod input;
|
||||
use std::io;
|
||||
use std::sync::{
|
||||
mpsc::{Receiver, Sender},
|
||||
Arc,
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
mod unix_input;
|
||||
#[cfg(windows)]
|
||||
mod windows_input;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crossterm_utils::Result;
|
||||
|
||||
pub use self::input::{input, TerminalInput};
|
||||
#[cfg(unix)]
|
||||
pub use self::unix_input::AsyncReader;
|
||||
#[cfg(unix)]
|
||||
pub use self::unix_input::SyncReader;
|
||||
#[cfg(unix)]
|
||||
use self::unix_input::UnixInput;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use self::windows_input::AsyncReader;
|
||||
#[cfg(windows)]
|
||||
@ -22,16 +26,12 @@ pub use self::windows_input::SyncReader;
|
||||
#[cfg(windows)]
|
||||
use self::windows_input::WindowsInput;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
mod input;
|
||||
|
||||
pub use self::input::{input, TerminalInput};
|
||||
use crossterm_utils::Result;
|
||||
use std::io;
|
||||
use std::sync::{
|
||||
mpsc::{Receiver, Sender},
|
||||
Arc,
|
||||
};
|
||||
#[cfg(unix)]
|
||||
mod unix_input;
|
||||
#[cfg(windows)]
|
||||
mod windows_input;
|
||||
|
||||
/// This trait defines the actions that can be performed with the terminal input.
|
||||
/// This trait can be implemented so that a concrete implementation of the ITerminalInput can fulfill
|
@ -1,9 +1,10 @@
|
||||
//! A module that contains all the actions related to reading input from the terminal.
|
||||
//! Like reading a line, reading a character and reading asynchronously.
|
||||
|
||||
use super::*;
|
||||
use std::io;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Allows you to read user input.
|
||||
///
|
||||
/// # Features:
|
||||
|
@ -1,14 +1,8 @@
|
||||
extern crate crossterm_screen;
|
||||
extern crate crossterm_utils;
|
||||
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
|
||||
mod input;
|
||||
mod sys;
|
||||
pub use crossterm_screen::{IntoRawMode, RawScreen};
|
||||
|
||||
pub use self::input::{
|
||||
input, AsyncReader, InputEvent, KeyEvent, MouseButton, MouseEvent, SyncReader, TerminalInput,
|
||||
};
|
||||
|
||||
pub use self::crossterm_screen::{IntoRawMode, RawScreen};
|
||||
mod input;
|
||||
mod sys;
|
||||
|
@ -57,8 +57,6 @@ crossterm_screen = "0.2"
|
||||
And import the `crossterm_screen` modules you want to use.
|
||||
|
||||
```rust
|
||||
extern crate crossterm_screen;
|
||||
|
||||
pub use crossterm_screen::{AlternateScreen, RawScreen};
|
||||
```
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
//! A module which provides some functionalities to work with the terminal screen.
|
||||
//! Like allowing you to switch between main and alternate screen or putting the terminal into raw mode.
|
||||
|
||||
mod alternate;
|
||||
mod raw;
|
||||
|
||||
pub use self::alternate::AlternateScreen;
|
||||
pub use self::raw::{IntoRawMode, RawScreen};
|
||||
|
||||
mod alternate;
|
||||
mod raw;
|
@ -53,8 +53,6 @@ crossterm_style = "0.3"
|
||||
And import the `crossterm_style` modules you want to use.
|
||||
|
||||
```rust
|
||||
extern crate crossterm_style;
|
||||
|
||||
pub use crossterm_style::{color, style, Attribute, Color, ColorType, ObjectStyle, StyledObject, TerminalColor, Colorize, Styler};
|
||||
```
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
|
||||
use crossterm_utils::{csi, write_cout, Result};
|
||||
|
||||
use crate::Colored;
|
||||
use crate::{Attribute, Color, ITerminalColor};
|
||||
use crate::{Attribute, Color, Colored, ITerminalColor};
|
||||
|
||||
#[inline]
|
||||
pub fn get_set_fg_ansi(fg_color: Color) -> String {
|
||||
|
@ -4,13 +4,16 @@
|
||||
use std::clone::Clone;
|
||||
use std::io;
|
||||
|
||||
use super::*;
|
||||
use crate::{Color, ITerminalColor};
|
||||
|
||||
#[cfg(windows)]
|
||||
use crossterm_utils::supports_ansi;
|
||||
use crossterm_utils::{impl_display, Command, Result};
|
||||
|
||||
#[cfg(windows)]
|
||||
use crate::winapi_color::WinApiColor;
|
||||
use crate::{Color, ITerminalColor};
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Allows you to style the terminal.
|
||||
///
|
||||
/// # Features:
|
||||
|
@ -1,9 +1,10 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use crossterm_utils::csi;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crossterm_utils::csi;
|
||||
|
||||
/// Enum with the different attributes to style your test.
|
||||
///
|
||||
/// There are few things to note:
|
||||
|
@ -1,6 +1,17 @@
|
||||
//! A module that contains all the actions related to the styling of the terminal.
|
||||
//! Like applying attributes to text and changing the foreground and background.
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
pub use crossterm_utils::{execute, queue, Command, ExecutableCommand, QueueableCommand, Result};
|
||||
|
||||
use self::ansi_color::AnsiColor;
|
||||
pub use self::color::{color, PrintStyledFont, SetAttr, SetBg, SetFg, TerminalColor};
|
||||
pub use self::enums::{Attribute, Color, Colored};
|
||||
pub use self::objectstyle::ObjectStyle;
|
||||
pub use self::styledobject::StyledObject;
|
||||
pub use self::traits::{Colorize, Styler};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod color;
|
||||
@ -13,19 +24,6 @@ mod ansi_color;
|
||||
#[cfg(windows)]
|
||||
mod winapi_color;
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use self::ansi_color::AnsiColor;
|
||||
#[cfg(windows)]
|
||||
use self::winapi_color::WinApiColor;
|
||||
pub use crossterm_utils::{execute, queue, Command, ExecutableCommand, QueueableCommand, Result};
|
||||
|
||||
pub use self::color::{color, PrintStyledFont, SetAttr, SetBg, SetFg, TerminalColor};
|
||||
pub use self::enums::{Attribute, Color, Colored};
|
||||
pub use self::objectstyle::ObjectStyle;
|
||||
pub use self::styledobject::StyledObject;
|
||||
pub use self::traits::{Colorize, Styler};
|
||||
|
||||
/// This trait defines the actions that can be performed with terminal colors.
|
||||
/// This trait can be implemented so that a concrete implementation of the ITerminalColor can fulfill
|
||||
/// the wishes to work on a specific platform.
|
||||
|
@ -5,10 +5,7 @@ use std::result;
|
||||
|
||||
use crossterm_utils::{csi, queue};
|
||||
|
||||
use crate::{Colorize, Styler};
|
||||
|
||||
use super::Attribute;
|
||||
use super::{color, Color, ObjectStyle, SetBg, SetFg};
|
||||
use super::{color, Attribute, Color, Colorize, ObjectStyle, SetBg, SetFg, Styler};
|
||||
|
||||
/// Contains both the style and the content which can be styled.
|
||||
#[derive(Clone)]
|
||||
|
@ -2,11 +2,12 @@
|
||||
//! This module is used for non supporting `ANSI` Windows terminals.
|
||||
|
||||
use std::io;
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::sync::Once;
|
||||
|
||||
use winapi::um::wincon;
|
||||
|
||||
use crossterm_utils::Result;
|
||||
use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer};
|
||||
use winapi::um::wincon;
|
||||
|
||||
use crate::{Color, Colored, ITerminalColor};
|
||||
|
||||
@ -187,5 +188,5 @@ fn original_console_color() -> u16 {
|
||||
return unsafe { ORIGINAL_CONSOLE_COLOR };
|
||||
}
|
||||
|
||||
static GET_ORIGINAL_CONSOLE_COLOR: Once = ONCE_INIT;
|
||||
static GET_ORIGINAL_CONSOLE_COLOR: Once = Once::new();
|
||||
static mut ORIGINAL_CONSOLE_COLOR: u16 = 0;
|
||||
|
@ -53,8 +53,6 @@ crossterm_terminal = "0.2"
|
||||
And import the `crossterm_terminal` modules you want to use.
|
||||
|
||||
```rust
|
||||
extern crate crossterm_terminal;
|
||||
|
||||
pub use crossterm_terminal::{terminal, Terminal, ClearType};
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
mod sys;
|
||||
mod terminal;
|
||||
pub use crossterm_utils::{execute, queue, Command, ExecutableCommand, QueueableCommand, Result};
|
||||
|
||||
pub use self::terminal::{terminal, Clear, ClearType, ScrollDown, ScrollUp, SetSize, Terminal};
|
||||
|
||||
pub use crossterm_utils::{execute, queue, Command, ExecutableCommand, QueueableCommand, Result};
|
||||
mod sys;
|
||||
mod terminal;
|
||||
|
@ -9,6 +9,7 @@ license = "MIT"
|
||||
keywords = ["terminal", "abstractions", "crossterm", "windows", "screen_buffer"]
|
||||
exclude = ["target", "Cargo.lock"]
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3.7", features = ["wincon"] }
|
||||
|
@ -1,10 +1,3 @@
|
||||
#[cfg(windows)]
|
||||
extern crate crossterm_winapi;
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
#[cfg(windows)]
|
||||
extern crate winapi;
|
||||
|
||||
pub use self::command::{Command, ExecutableCommand, Output, QueueableCommand};
|
||||
pub use self::error::{ErrorKind, Result};
|
||||
#[cfg(windows)]
|
||||
|
@ -9,6 +9,7 @@ license = "MIT"
|
||||
keywords = ["winapi", "abstractions", "crossterm", "windows", "screen_buffer"]
|
||||
exclude = ["target", "Cargo.lock"]
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
winapi = { version = "0.3.7", features = ["winbase","consoleapi","processenv", "handleapi"] }
|
@ -1,5 +1,3 @@
|
||||
extern crate crossterm_winapi;
|
||||
|
||||
use crossterm_winapi::{Console, ScreenBuffer};
|
||||
|
||||
fn set_background_color() -> std::io::Result<()> {
|
@ -1,5 +1,3 @@
|
||||
extern crate crossterm_winapi;
|
||||
|
||||
use crossterm_winapi::ConsoleMode;
|
||||
|
||||
fn change_console_mode() {
|
@ -1,5 +1,3 @@
|
||||
extern crate crossterm_winapi;
|
||||
|
||||
use crossterm_winapi::{Handle, HandleType};
|
||||
|
||||
#[allow(unused_variables)]
|
@ -1,5 +1,3 @@
|
||||
extern crate crossterm_winapi;
|
||||
|
||||
use crossterm_winapi::ScreenBuffer;
|
||||
|
||||
fn print_screen_buffer_information() {
|
@ -14,9 +14,7 @@ use winapi::um::{
|
||||
winnt::HANDLE,
|
||||
};
|
||||
|
||||
use InputRecord;
|
||||
|
||||
use super::{is_true, Coord, Handle, HandleType, WindowPositions};
|
||||
use super::{is_true, Coord, Handle, HandleType, InputRecord, WindowPositions};
|
||||
|
||||
/// Could be used to do some basic things with the console.
|
||||
pub struct Console {
|
||||
|
@ -1,8 +1,10 @@
|
||||
use super::{is_true, Handle, HandleType};
|
||||
use std::io::{Error, Result};
|
||||
|
||||
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
use super::{is_true, Handle, HandleType};
|
||||
|
||||
/// This abstracts away some WinaApi calls to set and get the console mode.
|
||||
///
|
||||
/// Wraps the underlying function call: [SetConsoleMode]
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::{Coord, Size, WindowPositions};
|
||||
use std::mem::zeroed;
|
||||
|
||||
use winapi::um::wincon::CONSOLE_SCREEN_BUFFER_INFO;
|
||||
|
||||
use std::mem::zeroed;
|
||||
use super::{Coord, Size, WindowPositions};
|
||||
|
||||
/// This type is a wrapper for `CONSOLE_SCREEN_BUFFER_INFO` and has some methods to extract information from it.
|
||||
///
|
||||
|
@ -1,12 +1,3 @@
|
||||
extern crate winapi;
|
||||
|
||||
mod console;
|
||||
mod console_mode;
|
||||
mod csbi;
|
||||
mod handle;
|
||||
mod screen_buffer;
|
||||
mod structs;
|
||||
|
||||
pub use self::{
|
||||
console::Console,
|
||||
console_mode::ConsoleMode,
|
||||
@ -19,6 +10,13 @@ pub use self::{
|
||||
},
|
||||
};
|
||||
|
||||
mod console;
|
||||
mod console_mode;
|
||||
mod csbi;
|
||||
mod handle;
|
||||
mod screen_buffer;
|
||||
mod structs;
|
||||
|
||||
/// Parses the given integer to an bool by checking if the value is 0 or 1.
|
||||
/// This is currently used for checking if a WinApi called succeeded, this might be moved into a macro at some time.
|
||||
/// So please don't use this :(.
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! This contains the logic for working with the console buffer.
|
||||
|
||||
use super::{is_true, Handle, HandleType, ScreenBufferInfo};
|
||||
use std::io::{Error, Result};
|
||||
use std::mem::size_of;
|
||||
|
||||
use winapi::{
|
||||
shared::minwindef::TRUE,
|
||||
@ -15,8 +16,7 @@ use winapi::{
|
||||
},
|
||||
};
|
||||
|
||||
use std::io::{Error, Result};
|
||||
use std::mem::size_of;
|
||||
use super::{is_true, Handle, HandleType, ScreenBufferInfo};
|
||||
|
||||
pub struct ScreenBuffer {
|
||||
handle: Handle,
|
||||
|
@ -1,8 +1,3 @@
|
||||
mod coord;
|
||||
mod input;
|
||||
mod size;
|
||||
mod window_coords;
|
||||
|
||||
pub use self::coord::Coord;
|
||||
pub use self::input::{
|
||||
ButtonState, ControlKeyState, EventFlags, InputEventType, InputRecord, KeyEventRecord,
|
||||
@ -10,3 +5,8 @@ pub use self::input::{
|
||||
};
|
||||
pub use self::size::Size;
|
||||
pub use self::window_coords::WindowPositions;
|
||||
|
||||
mod coord;
|
||||
mod input;
|
||||
mod size;
|
||||
mod window_coords;
|
@ -14,7 +14,8 @@ use winapi::um::wincon::{
|
||||
INPUT_RECORD_Event, KEY_EVENT_RECORD_uChar, FOCUS_EVENT, INPUT_RECORD, KEY_EVENT,
|
||||
KEY_EVENT_RECORD, MENU_EVENT, MOUSE_EVENT, MOUSE_EVENT_RECORD, WINDOW_BUFFER_SIZE_EVENT,
|
||||
};
|
||||
use Coord;
|
||||
|
||||
use super::coord::Coord;
|
||||
|
||||
/// Describes a keyboard input event in a console INPUT_RECORD structure.
|
||||
/// link: [https://docs.microsoft.com/en-us/windows/console/key-event-record-str]
|
||||
|
@ -55,8 +55,6 @@ Now we have covered the basics of styling lets go over to some examples.
|
||||
|
||||
_setup the basics_
|
||||
```rust
|
||||
extern crate crossterm;
|
||||
|
||||
use crossterm::{Colored, Color, Attribute, Styler, Colorize};
|
||||
|
||||
fn main() {
|
||||
|
@ -1,7 +1,6 @@
|
||||
extern crate crossterm;
|
||||
use std::{io, thread, time};
|
||||
|
||||
use crossterm::{style, AlternateScreen, ClearType, Color, Crossterm};
|
||||
use std::{io, thread, time};
|
||||
|
||||
fn print_wait_screen() -> io::Result<()> {
|
||||
let crossterm = Crossterm::new();
|
||||
|
@ -1,11 +1,10 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern crate crossterm;
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
use crossterm::{
|
||||
execute, queue, Clear, ClearType, ExecutableCommand, Goto, Output, QueueableCommand,
|
||||
};
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
/// execute commands by using normal functions
|
||||
fn execute_command_directly_using_functions() {
|
||||
|
@ -1,13 +1,11 @@
|
||||
extern crate crossterm;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{thread, time};
|
||||
|
||||
use crossterm::{
|
||||
cursor, input, terminal, ClearType, Crossterm, InputEvent, KeyEvent, RawScreen, Terminal,
|
||||
TerminalCursor,
|
||||
};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{thread, time};
|
||||
|
||||
fn main() {
|
||||
let _screen = RawScreen::into_raw_mode();
|
||||
cursor().hide().expect("Couldn't hide cursor");
|
||||
|
@ -1,11 +1,10 @@
|
||||
// Remove once the TODO below is fixed
|
||||
#![allow(unused_variables)]
|
||||
|
||||
extern crate crossterm;
|
||||
|
||||
use crossterm::{Color, Crossterm};
|
||||
|
||||
// use the `Crossterm` to get an instance to the cursor module | demonstration.
|
||||
pub fn main() {
|
||||
fn main() {
|
||||
// Create the crossterm type to access different modules.
|
||||
let crossterm = Crossterm::new();
|
||||
|
||||
|
@ -2,10 +2,9 @@
|
||||
//! Examples of actions that could be performed with the cursor.
|
||||
//!
|
||||
|
||||
extern crate crossterm_cursor;
|
||||
use std::io;
|
||||
|
||||
use crossterm_cursor::cursor;
|
||||
use std::io;
|
||||
|
||||
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
||||
pub fn goto() -> io::Result<()> {
|
||||
|
@ -1,6 +1,4 @@
|
||||
extern crate crossterm;
|
||||
|
||||
use self::crossterm::input;
|
||||
use crossterm::input;
|
||||
|
||||
pub fn read_char() {
|
||||
let input = input();
|
||||
|
@ -1,7 +1,6 @@
|
||||
extern crate crossterm;
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
use crossterm::{input, InputEvent, KeyEvent, MouseButton, MouseEvent, RawScreen};
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
fn process_input_event(key_event: InputEvent) -> bool {
|
||||
match key_event {
|
||||
|
@ -2,10 +2,10 @@
|
||||
name = "first_depth_search"
|
||||
version = "0.1.0"
|
||||
authors = ["TimonPost <timonpost@hotmail.nl>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.4.2"
|
||||
|
||||
[dependencies.crossterm]
|
||||
path = "../../../"
|
||||
branch = "master"
|
@ -1,14 +1,14 @@
|
||||
//! Implementation of the first depth search algorithm
|
||||
|
||||
use std::io::Write;
|
||||
use std::{thread, time};
|
||||
|
||||
use crossterm::{execute, Color, Colorize, Goto, Hide, PrintStyledFont, Result, SetBg, SetFg};
|
||||
use rand;
|
||||
use rand::distributions::{IndependentSample, Range};
|
||||
|
||||
use super::map::Map;
|
||||
use super::variables::{Direction, Position};
|
||||
use std::io::Write;
|
||||
|
||||
use super::rand;
|
||||
use super::rand::distributions::{IndependentSample, Range};
|
||||
use std::{thread, time};
|
||||
|
||||
use crossterm::{execute, Color, Colorize, Command, Goto, Hide, PrintStyledFont, SetBg, SetFg};
|
||||
|
||||
pub struct FirstDepthSearch {
|
||||
direction: Direction,
|
||||
@ -29,7 +29,7 @@ impl FirstDepthSearch {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
pub fn start(&mut self) -> Result<()> {
|
||||
self.is_terminated = false;
|
||||
|
||||
// push first position on the stack
|
||||
@ -40,7 +40,7 @@ impl FirstDepthSearch {
|
||||
Hide,
|
||||
SetFg(Color::Green),
|
||||
SetBg(Color::Black)
|
||||
);
|
||||
)?;
|
||||
|
||||
// loop until there are now items left in the stack.
|
||||
loop {
|
||||
@ -65,10 +65,12 @@ impl FirstDepthSearch {
|
||||
::std::io::stdout(),
|
||||
Goto(x, y),
|
||||
PrintStyledFont(" ".on_yellow())
|
||||
);
|
||||
)?;
|
||||
|
||||
thread::sleep(time::Duration::from_millis(1));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// With this function we are choosing an random neighbor that we havent visited yet.
|
||||
|
@ -1,54 +1,50 @@
|
||||
extern crate crossterm;
|
||||
extern crate rand;
|
||||
use std::io::{stdout, Write};
|
||||
use std::iter::Iterator;
|
||||
use std::{thread, time};
|
||||
|
||||
use crossterm::{
|
||||
color, cursor, execute, input, style, terminal, AlternateScreen, Clear, ClearType, Color, Goto,
|
||||
Hide, InputEvent, KeyEvent, Output, PrintStyledFont, RawScreen, Result, SetBg, SetFg, SetSize,
|
||||
};
|
||||
|
||||
use self::variables::{Position, Size};
|
||||
|
||||
mod algorithm;
|
||||
mod map;
|
||||
mod messages;
|
||||
mod variables;
|
||||
|
||||
use self::crossterm::{
|
||||
color, cursor, execute, input, style, terminal, AlternateScreen, Clear, ClearType, Color,
|
||||
Colored, Command, Crossterm, Goto, Hide, InputEvent, KeyEvent, Output, PrintStyledFont,
|
||||
RawScreen, SetBg, SetFg, SetSize,
|
||||
};
|
||||
use self::variables::{Position, Size};
|
||||
|
||||
use std::io::{stdout, Write};
|
||||
use std::iter::Iterator;
|
||||
use std::{thread, time};
|
||||
|
||||
fn main() {
|
||||
run();
|
||||
fn main() -> Result<()> {
|
||||
run()
|
||||
}
|
||||
|
||||
/// run the program
|
||||
pub fn run() {
|
||||
fn run() -> Result<()> {
|
||||
// let screen = RawScreen::into_raw_mode().expect("failed to enable raw modes");
|
||||
print_welcome_screen();
|
||||
start_algorithm();
|
||||
exit();
|
||||
print_welcome_screen()?;
|
||||
start_algorithm()?;
|
||||
exit()
|
||||
}
|
||||
|
||||
fn start_algorithm() {
|
||||
fn start_algorithm() -> Result<()> {
|
||||
// we first want to switch to alternate screen. On the alternate screen we are going to run or firstdepthsearch algorithm
|
||||
if let Ok(ref _alternate_screen) = AlternateScreen::to_alternate(true) {
|
||||
let ref _alternate_screen = AlternateScreen::to_alternate(true)?;
|
||||
// setup the map size and the position to start searching for a path.
|
||||
let map_size = Size::new(50, 40);
|
||||
let start_pos = Position::new(10, 10);
|
||||
|
||||
// create and render the map. Or map border is going to have an █ look and inside the map is just a space.
|
||||
let mut map = map::Map::new(map_size, '█', ' ');
|
||||
map.render_map();
|
||||
map.render_map()?;
|
||||
|
||||
// create the algorithm and start it on the alternate screen. Make sure to pass the refrence to the AlternateScreen screen.
|
||||
let mut algorithm = algorithm::FirstDepthSearch::new(map, start_pos);
|
||||
algorithm.start();
|
||||
}
|
||||
algorithm.start()
|
||||
}
|
||||
|
||||
fn print_welcome_screen() {
|
||||
fn print_welcome_screen() -> Result<()> {
|
||||
// we have to keep this screen arround to prevent te
|
||||
let _screen = RawScreen::into_raw_mode();
|
||||
let _screen = RawScreen::into_raw_mode()?;
|
||||
|
||||
execute!(
|
||||
stdout(),
|
||||
@ -63,14 +59,14 @@ fn print_welcome_screen() {
|
||||
Output("The first depth search algorithm will start in: Seconds".to_string()),
|
||||
Goto(0, 11),
|
||||
Output("Press `q` to abort the program".to_string())
|
||||
);
|
||||
)?;
|
||||
|
||||
let mut stdin = input().read_async();
|
||||
|
||||
// print some progress example.
|
||||
for i in (1..5).rev() {
|
||||
if let Some(InputEvent::Keyboard(KeyEvent::Char('q'))) = stdin.next() {
|
||||
exit();
|
||||
exit()?;
|
||||
terminal().exit();
|
||||
break;
|
||||
} else {
|
||||
@ -81,18 +77,20 @@ fn print_welcome_screen() {
|
||||
SetFg(Color::Red),
|
||||
SetBg(Color::Blue),
|
||||
Output(i.to_string())
|
||||
);
|
||||
)?;
|
||||
}
|
||||
|
||||
color().reset();
|
||||
color().reset()?;
|
||||
|
||||
// 1 second delay
|
||||
thread::sleep(time::Duration::from_secs(1));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn exit() {
|
||||
RawScreen::disable_raw_mode().expect("failed to disable raw modes.");
|
||||
cursor().show();
|
||||
color().reset();
|
||||
fn exit() -> Result<()> {
|
||||
RawScreen::disable_raw_mode().expect("Failed to disable raw modes.");
|
||||
cursor().show()?;
|
||||
color().reset()
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use super::variables::{Cell, Position, Size};
|
||||
use crossterm::{queue, Color, Command, Crossterm, Goto, PrintStyledFont};
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
use crossterm::{queue, Color, Crossterm, Goto, PrintStyledFont, Result};
|
||||
|
||||
use super::variables::{Cell, Position, Size};
|
||||
|
||||
pub struct Map {
|
||||
pub map: Vec<Vec<Cell>>,
|
||||
pub size: Size,
|
||||
@ -43,7 +45,7 @@ impl Map {
|
||||
}
|
||||
|
||||
// render the map on the screen.
|
||||
pub fn render_map(&mut self) {
|
||||
pub fn render_map(&mut self) -> Result<()> {
|
||||
let crossterm = Crossterm::new();
|
||||
|
||||
for row in self.map.iter_mut() {
|
||||
@ -56,10 +58,12 @@ impl Map {
|
||||
stdout(),
|
||||
Goto(column.position.x as u16, column.position.y as u16),
|
||||
PrintStyledFont(crossterm.style(column.look).on(column.color))
|
||||
);
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// check if position in the map at the given coords is visted.
|
||||
|
@ -1,4 +0,0 @@
|
||||
mod map;
|
||||
mod messages;
|
||||
mod variables;
|
||||
mod algorithm;
|
@ -1,6 +1,4 @@
|
||||
extern crate crossterm;
|
||||
|
||||
use self::crossterm::Color;
|
||||
use crossterm::Color;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Direction {
|
||||
|
@ -2,6 +2,7 @@
|
||||
name = "snake"
|
||||
version = "0.1.0"
|
||||
authors = ["TimonPost <timonpost@hotmail.nl>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.4.2"
|
||||
|
@ -1,33 +1,30 @@
|
||||
extern crate crossterm;
|
||||
extern crate rand;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{stdout, Write};
|
||||
use std::iter::Iterator;
|
||||
use std::{thread, time};
|
||||
|
||||
use map::Map;
|
||||
use snake::Snake;
|
||||
use variables::{Direction, Position, Size};
|
||||
|
||||
use crossterm::{
|
||||
execute, input, style, AsyncReader, Clear, ClearType, Color, Colorize, Crossterm, Goto,
|
||||
InputEvent, KeyEvent, PrintStyledFont, RawScreen, Result, Show,
|
||||
};
|
||||
|
||||
mod map;
|
||||
mod messages;
|
||||
mod snake;
|
||||
mod variables;
|
||||
|
||||
use self::crossterm::{
|
||||
execute, input, style, AsyncReader, Clear, ClearType, Color, Colorize, Command, Crossterm,
|
||||
Goto, InputEvent, KeyEvent, Output, PrintStyledFont, RawScreen, Show,
|
||||
};
|
||||
|
||||
use map::Map;
|
||||
use snake::Snake;
|
||||
use variables::{Direction, Position, Size};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::{stdout, Write};
|
||||
use std::iter::Iterator;
|
||||
use std::{thread, time};
|
||||
|
||||
fn main() {
|
||||
let map_size = ask_size();
|
||||
fn main() -> Result<()> {
|
||||
let map_size = ask_size()?;
|
||||
|
||||
// screen has to be in raw mode in order for the key presses not to be printed to the screen.
|
||||
let raw = RawScreen::into_raw_mode();
|
||||
let _raw = RawScreen::into_raw_mode();
|
||||
let crossterm = Crossterm::new();
|
||||
|
||||
crossterm.cursor().hide();
|
||||
crossterm.cursor().hide()?;
|
||||
|
||||
// initialize free positions for the game map.
|
||||
let mut free_positions: HashMap<String, Position> =
|
||||
@ -35,7 +32,7 @@ fn main() {
|
||||
|
||||
// render the map
|
||||
let mut map = Map::new(map_size);
|
||||
map.render_map(&mut free_positions);
|
||||
map.render_map(&mut free_positions)?;
|
||||
|
||||
let mut snake = Snake::new();
|
||||
|
||||
@ -44,7 +41,7 @@ fn main() {
|
||||
free_positions.remove_entry(format!("{},{}", part.position.x, part.position.y).as_str());
|
||||
}
|
||||
|
||||
map.spawn_food(&free_positions);
|
||||
map.spawn_food(&free_positions)?;
|
||||
|
||||
let mut stdin = crossterm.input().read_async();
|
||||
let mut snake_direction = Direction::Right;
|
||||
@ -55,21 +52,21 @@ fn main() {
|
||||
snake_direction = new_direction;
|
||||
}
|
||||
|
||||
snake.move_snake(&snake_direction, &mut free_positions);
|
||||
snake.move_snake(&snake_direction, &mut free_positions)?;
|
||||
|
||||
if map.is_out_of_bounds(snake.snake_parts[0].position) {
|
||||
break;
|
||||
}
|
||||
|
||||
snake.draw_snake();
|
||||
snake.draw_snake()?;
|
||||
|
||||
if snake.has_eaten_food(map.foot_pos) {
|
||||
map.spawn_food(&free_positions);
|
||||
map.spawn_food(&free_positions)?;
|
||||
}
|
||||
|
||||
thread::sleep(time::Duration::from_millis(400));
|
||||
}
|
||||
game_over_screen();
|
||||
game_over_screen()
|
||||
}
|
||||
|
||||
fn update_direction(reader: &mut AsyncReader) -> Option<Direction> {
|
||||
@ -96,7 +93,7 @@ fn update_direction(reader: &mut AsyncReader) -> Option<Direction> {
|
||||
None
|
||||
}
|
||||
|
||||
fn ask_size() -> Size {
|
||||
fn ask_size() -> Result<Size> {
|
||||
execute!(
|
||||
stdout(),
|
||||
Clear(ClearType::All),
|
||||
@ -105,7 +102,7 @@ fn ask_size() -> Size {
|
||||
Goto(0, 15),
|
||||
PrintStyledFont("Enter map width:".green().on_yellow()),
|
||||
Goto(17, 15)
|
||||
);
|
||||
)?;
|
||||
|
||||
let width = input().read_line().unwrap();
|
||||
|
||||
@ -113,7 +110,7 @@ fn ask_size() -> Size {
|
||||
stdout(),
|
||||
PrintStyledFont("\r\nEnter map height:".green().on_yellow()),
|
||||
Goto(17, 17)
|
||||
);
|
||||
)?;
|
||||
|
||||
let height = input().read_line().unwrap();
|
||||
|
||||
@ -121,17 +118,17 @@ fn ask_size() -> Size {
|
||||
let parsed_width = width.parse::<usize>().unwrap();
|
||||
let parsed_height = height.parse::<usize>().unwrap();
|
||||
|
||||
execute!(stdout(), Clear(ClearType::All));
|
||||
execute!(stdout(), Clear(ClearType::All))?;
|
||||
|
||||
return Size::new(parsed_width, parsed_height);
|
||||
Ok(Size::new(parsed_width, parsed_height))
|
||||
}
|
||||
|
||||
fn game_over_screen() {
|
||||
fn game_over_screen() -> Result<()> {
|
||||
execute!(
|
||||
stdout(),
|
||||
Clear(ClearType::All),
|
||||
Goto(0, 0),
|
||||
PrintStyledFont(style(format!("{}", messages::END_MESSAGE.join("\n\r"))).with(Color::Red)),
|
||||
Show
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
use super::variables::{Position, Size};
|
||||
|
||||
use crossterm::{cursor, queue, Colorize, Command, Goto, PrintStyledFont, TerminalCursor};
|
||||
|
||||
use rand::distributions::{IndependentSample, Range};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
use crossterm::{queue, Colorize, Goto, PrintStyledFont, Result};
|
||||
use rand;
|
||||
use rand::distributions::{IndependentSample, Range};
|
||||
|
||||
use super::variables::{Position, Size};
|
||||
|
||||
pub struct Map {
|
||||
pub size: Size,
|
||||
@ -23,7 +21,7 @@ impl Map {
|
||||
}
|
||||
|
||||
// render the map on the screen.
|
||||
pub fn render_map(&mut self, free_positions: &mut HashMap<String, Position>) {
|
||||
pub fn render_map(&mut self, free_positions: &mut HashMap<String, Position>) -> Result<()> {
|
||||
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) {
|
||||
@ -31,12 +29,13 @@ impl Map {
|
||||
stdout(),
|
||||
Goto(x as u16, y as u16),
|
||||
PrintStyledFont("█".magenta())
|
||||
);
|
||||
)?;
|
||||
} else {
|
||||
free_positions.insert(format!("{},{}", x, y), Position::new(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_out_of_bounds(&self, new_pos: Position) -> bool {
|
||||
@ -49,21 +48,17 @@ impl Map {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_food_eaten(&self, snake_head: Position) -> bool {
|
||||
snake_head.x == self.foot_pos.x && snake_head.y == self.foot_pos.y
|
||||
}
|
||||
|
||||
pub fn spawn_food(&mut self, free_positions: &HashMap<String, Position>) {
|
||||
pub fn spawn_food(&mut self, free_positions: &HashMap<String, Position>) -> Result<()> {
|
||||
let index = Range::new(0, free_positions.len()).ind_sample(&mut rand::thread_rng());
|
||||
self.foot_pos = free_positions.values().skip(index).next().unwrap().clone();
|
||||
self.draw_food();
|
||||
self.draw_food()
|
||||
}
|
||||
|
||||
fn draw_food(&self) {
|
||||
fn draw_food(&self) -> Result<()> {
|
||||
queue!(
|
||||
stdout(),
|
||||
Goto(self.foot_pos.x as u16, self.foot_pos.y as u16),
|
||||
PrintStyledFont("$".green())
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
use super::variables::{Direction, Position};
|
||||
use crossterm::Crossterm;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crossterm::Result;
|
||||
|
||||
use super::variables::{Direction, Position};
|
||||
|
||||
pub struct Part {
|
||||
pub position: Position,
|
||||
}
|
||||
@ -32,12 +33,12 @@ impl Snake {
|
||||
&mut self,
|
||||
direction: &Direction,
|
||||
free_positions: &mut HashMap<String, Position>,
|
||||
) {
|
||||
) -> Result<()> {
|
||||
let count = self.snake_parts.len();
|
||||
|
||||
for (index, ref mut snake_part) in self.snake_parts.iter_mut().enumerate() {
|
||||
if index == count - 1 {
|
||||
snake_part.position.remove();
|
||||
snake_part.position.remove()?;
|
||||
free_positions.insert(
|
||||
format!("{},{}", snake_part.position.x, snake_part.position.y),
|
||||
snake_part.position,
|
||||
@ -63,12 +64,14 @@ impl Snake {
|
||||
snake_part.position = new_pos;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn draw_snake(&mut self) {
|
||||
pub fn draw_snake(&mut self) -> Result<()> {
|
||||
for snake_part in self.snake_parts.iter_mut() {
|
||||
snake_part.position.draw("■");
|
||||
snake_part.position.draw("■")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn has_eaten_food(&mut self, food_pos: Position) -> bool {
|
||||
|
@ -1,9 +1,8 @@
|
||||
extern crate crossterm;
|
||||
|
||||
use self::crossterm::{style, Color, Crossterm, TerminalCursor};
|
||||
use std::io::stdout;
|
||||
use std::io::Write;
|
||||
|
||||
use crossterm::{style, Color, Crossterm, Result, TerminalCursor};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Direction {
|
||||
Up = 0,
|
||||
@ -23,19 +22,21 @@ impl Position {
|
||||
Position { x, y }
|
||||
}
|
||||
|
||||
pub fn draw(&self, val: &str) {
|
||||
pub fn draw(&self, val: &str) -> Result<()> {
|
||||
let cursor = TerminalCursor::new();
|
||||
cursor.goto(self.x as u16, self.y as u16);
|
||||
cursor.goto(self.x as u16, self.y as u16)?;
|
||||
|
||||
print!("{}", style(val).with(Color::Red));
|
||||
stdout().flush();
|
||||
stdout().flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove(&self) {
|
||||
pub fn remove(&self) -> Result<()> {
|
||||
let crossterm = Crossterm::new();
|
||||
|
||||
crossterm.cursor().goto(self.x as u16, self.y as u16);
|
||||
crossterm.terminal().write(" ");
|
||||
crossterm.cursor().goto(self.x as u16, self.y as u16)?;
|
||||
crossterm.terminal().write(" ")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
extern crate crossterm;
|
||||
|
||||
use crossterm::{style, AlternateScreen, ClearType, Color, Crossterm};
|
||||
|
||||
use std::io::{self, stdout, Write};
|
||||
use std::{thread, time};
|
||||
|
||||
use crossterm::{style, AlternateScreen, ClearType, Color, Crossterm};
|
||||
|
||||
fn print_wait_screen() -> io::Result<()> {
|
||||
let crossterm = Crossterm::new();
|
||||
let terminal = crossterm.terminal();
|
||||
|
@ -1,9 +1,7 @@
|
||||
//!
|
||||
//! Examples of coloring the terminal.
|
||||
//!
|
||||
extern crate crossterm;
|
||||
|
||||
use self::crossterm::{color, Attribute, Color, Colored, Colorize, Styler};
|
||||
use crossterm::{color, Attribute, Color, Colored, Colorize, Styler};
|
||||
|
||||
/// print some red text | demonstration.
|
||||
pub fn paint_foreground() {
|
||||
|
@ -2,10 +2,9 @@
|
||||
//! Terminal Examples
|
||||
//!
|
||||
|
||||
extern crate crossterm;
|
||||
use std::io;
|
||||
|
||||
use crossterm::{cursor, terminal, ClearType};
|
||||
use std::io;
|
||||
|
||||
fn print_test_data() {
|
||||
for i in 0..100 {
|
||||
|
33
src/lib.rs
33
src/lib.rs
@ -13,43 +13,28 @@
|
||||
//! - [Crossterm Cursor](https://crates.io/crates/crossterm_cursor)
|
||||
//! - [Crossterm Terminal](https://crates.io/crates/crossterm_terminal)
|
||||
|
||||
extern crate crossterm_utils;
|
||||
|
||||
#[cfg(feature = "cursor")]
|
||||
extern crate crossterm_cursor;
|
||||
#[cfg(feature = "input")]
|
||||
extern crate crossterm_input;
|
||||
#[cfg(feature = "screen")]
|
||||
extern crate crossterm_screen;
|
||||
#[cfg(feature = "style")]
|
||||
extern crate crossterm_style;
|
||||
#[cfg(feature = "terminal")]
|
||||
extern crate crossterm_terminal;
|
||||
|
||||
mod crossterm;
|
||||
|
||||
#[cfg(feature = "cursor")]
|
||||
pub use self::crossterm_cursor::{
|
||||
pub use crossterm_cursor::{
|
||||
cursor, BlinkOff, BlinkOn, Down, Goto, Hide, Left, ResetPos, Right, SavePos, Show,
|
||||
TerminalCursor, Up,
|
||||
};
|
||||
#[cfg(feature = "input")]
|
||||
pub use self::crossterm_input::{
|
||||
pub use crossterm_input::{
|
||||
input, AsyncReader, InputEvent, KeyEvent, MouseButton, MouseEvent, SyncReader, TerminalInput,
|
||||
};
|
||||
#[cfg(feature = "screen")]
|
||||
pub use self::crossterm_screen::{AlternateScreen, IntoRawMode, RawScreen};
|
||||
pub use crossterm_screen::{AlternateScreen, IntoRawMode, RawScreen};
|
||||
#[cfg(feature = "style")]
|
||||
pub use self::crossterm_style::{
|
||||
pub use crossterm_style::{
|
||||
color, style, Attribute, Color, Colored, Colorize, ObjectStyle, PrintStyledFont, SetAttr,
|
||||
SetBg, SetFg, StyledObject, Styler, TerminalColor,
|
||||
};
|
||||
#[cfg(feature = "terminal")]
|
||||
pub use self::crossterm_terminal::{
|
||||
terminal, Clear, ClearType, ScrollDown, ScrollUp, SetSize, Terminal,
|
||||
pub use crossterm_terminal::{terminal, Clear, ClearType, ScrollDown, ScrollUp, SetSize, Terminal};
|
||||
pub use crossterm_utils::{
|
||||
execute, queue, Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result,
|
||||
};
|
||||
|
||||
pub use self::crossterm::Crossterm;
|
||||
pub use self::crossterm_utils::{
|
||||
execute, queue, Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result,
|
||||
};
|
||||
|
||||
mod crossterm;
|
||||
|
Loading…
Reference in New Issue
Block a user