2018 edition (#222)

This commit is contained in:
Zrzka 2019-09-16 13:34:08 +02:00 committed by Timon
parent 7cda56bc9a
commit 5494525d89
76 changed files with 292 additions and 356 deletions

View File

@ -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

View File

@ -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"]

View File

@ -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};
```

View File

@ -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);

View File

@ -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.

View File

@ -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 {

View File

@ -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.
///

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 } {

View File

@ -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};
```

View File

@ -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() {

View File

@ -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();

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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};
```

View File

@ -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;

View File

@ -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};
```

View File

@ -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 {

View File

@ -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:

View File

@ -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:

View File

@ -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.

View File

@ -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)]

View File

@ -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;

View File

@ -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};
```

View File

@ -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;

View File

@ -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"] }

View File

@ -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)]

View File

@ -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"] }

View File

@ -1,5 +1,3 @@
extern crate crossterm_winapi;
use crossterm_winapi::{Console, ScreenBuffer};
fn set_background_color() -> std::io::Result<()> {

View File

@ -1,5 +1,3 @@
extern crate crossterm_winapi;
use crossterm_winapi::ConsoleMode;
fn change_console_mode() {

View File

@ -1,5 +1,3 @@
extern crate crossterm_winapi;
use crossterm_winapi::{Handle, HandleType};
#[allow(unused_variables)]

View File

@ -1,5 +1,3 @@
extern crate crossterm_winapi;
use crossterm_winapi::ScreenBuffer;
fn print_screen_buffer_information() {

View File

@ -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 {

View File

@ -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]

View File

@ -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.
///

View File

@ -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 :(.

View File

@ -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,

View File

@ -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;

View File

@ -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]

View File

@ -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() {

View File

@ -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();

View File

@ -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() {

View File

@ -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");

View File

@ -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();

View File

@ -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<()> {

View File

@ -1,6 +1,4 @@
extern crate crossterm;
use self::crossterm::input;
use crossterm::input;
pub fn read_char() {
let input = input();

View File

@ -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 {

View File

@ -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"

View File

@ -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.

View File

@ -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) {
// 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);
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();
// 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()?;
// 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();
}
// 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()
}
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()
}

View File

@ -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.

View File

@ -1,4 +0,0 @@
mod map;
mod messages;
mod variables;
mod algorithm;

View File

@ -1,6 +1,4 @@
extern crate crossterm;
use self::crossterm::Color;
use crossterm::Color;
#[derive(Copy, Clone, Debug)]
pub enum Direction {

View File

@ -2,6 +2,7 @@
name = "snake"
version = "0.1.0"
authors = ["TimonPost <timonpost@hotmail.nl>"]
edition = "2018"
[dependencies]
rand = "0.4.2"

View File

@ -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
);
)
}

View File

@ -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())
);
)
}
}

View File

@ -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 {

View File

@ -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(())
}
}

View File

@ -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();

View File

@ -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() {

View File

@ -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 {

View File

@ -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;