Skip to content
This repository has been archived by the owner on Oct 22, 2019. It is now read-only.

Internal refactoring and docs #2

Merged
merged 11 commits into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Build only pushed (merged) master or any pull request. This avoids the
# pull request to be build twice.
branches:
only:
- master

language: rust

rust:
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Version master

## Breaking changes

- `sys` module is no longer public

# Version 0.3.1

- Maintenance release only
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ crossterm_winapi = { version = "0.2.1" }

[dependencies]
crossterm_utils = { version = "0.3.1" }
lazy_static = "1.4"
161 changes: 50 additions & 111 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,140 +2,79 @@

# Crossterm Cursor

This crate allows you to move the terminal cursor cross-platform.
It supports all UNIX and windows terminals down to windows 7 (not all terminals are tested
see [Tested Terminals](#tested-terminals) for more info)
This crate allows you to work with the terminal cursor. It supports all UNIX and Windows terminals down
to Windows 7 (not all terminals are tested, see the
[Tested Terminals](https://github.com/crossterm-rs/crossterm/blob/master/README.md#tested-terminals) for more info).

This crate is a sub-crate of [crossterm](https://crates.io/crates/crossterm) to move the cursor, and can be
use individually.
`crossterm_cursor` is a sub-crate of the [crossterm](https://crates.io/crates/crossterm) crate. You can use it
directly, but it's **highly recommended** to use the [crossterm](https://crates.io/crates/crossterm) crate with
the `cursor` feature enabled (see [feature flags](https://crossterm-rs.github.io/crossterm/docs/feature_flags.html)
for more info).

Other sub-crates are:
## Future

- [crossterm_style](https://crates.io/crates/crossterm_style)
- [crossterm_terminal](https://crates.io/crates/crossterm_terminal)
- [crossterm_screen](https://crates.io/crates/crossterm_screen)
- [crossterm_input](https://crates.io/crates/crossterm_input)

When you want to use other modules as well you might want to use crossterm with
[feature flags](https://crossterm-rs.github.io/crossterm/docs/feature_flags.html).

## Table of contents:
> The `crossterm_cursor` crate code will be moved to the `crossterm` crate (it's reexported there now).
> Date is not set yet, but it doesn't make a lot of sense to start a new project with it. Please, use
> the `crossterm` crate with the `cursor` feature enabled.

- [Getting started](#getting-started)
- [Useful links](#useful-links)
- [Features](#features)
- [Examples](#examples)
- [Tested Terminals](#tested-terminals)
- [Authors](#authors)
- [License](#license)
Issues in this repository are disabled for the same reason. Please, report all issues in the
[crossterm-rs/crossterm](https://github.com/crossterm-rs/crossterm/issues) repository.

## Getting Started
## Features

All examples of how `crossterm_cursor` works can be found in the [examples](https://github.com/crossterm-rs/examples)
repository.
- Cross-platform
- Multi-threaded (send, sync)
- Detailed documentation
- Few dependencies
- Cursor
- Move the cursor N times (up, down, left, right)
- Set/get the cursor position
- Store the cursor position and restore to it later
- Hide/show the cursor
- Enable/disable cursor blinking (not all terminals do support this feature)

Add the `crossterm_cursor` package to your `Cargo.toml` file.
## Getting started

```
[dependencies]
crossterm_cursor = "0.3"
```
Import the `crossterm_cursor` modules you want to use.
<details>
<summary>
Click to show Cargo.toml.
</summary>

```rust
pub use crossterm_cursor::{cursor, TerminalCursor};
```toml
[dependencies]
# All crossterm features are enabled by default.
crossterm = "0.11"
```

### Useful Links
</details>
<p></p>

- [Documentation](https://docs.rs/crossterm_cursor/)
- [Crates.io](https://crates.io/crates/crossterm_cursor)
- [Examples](https://github.com/crossterm-rs/examples)
```rust
use std::io::{stdout, Write};
use crossterm::{execute, Goto, Result};

## Features
These are the features of this crate:

- Cross-platform
- Multithreaded (send, sync)
- Detailed Documentation
- Few Dependencies
- Cursor
- Moving _n_ times (up, down, left, right)
- Position (set/get)
- Store cursor position and resetting to that later
- Hiding/Showing
- Blinking Cursor (only some terminals are supporting this)

## Command API

My first recommendation is to use the [command API](https://crossterm-rs.github.io/crossterm/docs/command.html),
because this might replace some of the existing API in the future. It is more convenient, faster and
easier to use.

## Examples

The [examples](https://github.com/crossterm-rs/examples) repository has more complete and verbose examples.

```rust
use crossterm_cursor::cursor;

let mut cursor = cursor();

/// Moving the cursor
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);

// Move the cursor up,right,down,left 3 cells.
cursor.move_up(3);
cursor.move_right(3);
cursor.move_down(3);
cursor.move_left(3);

/// Safe the current cursor position to recall later
// Goto X: 5 Y: 5
cursor.goto(5,5);
// Safe cursor position: X: 5 Y: 5
cursor.save_position();
// Goto X: 5 Y: 20
cursor.goto(5,20);
// Print at X: 5 Y: 20.
print!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.restore_position();
// Print 'Back' at X: 5 Y: 5.
print!("Back");

// hide cursor
cursor.hide();
// show cursor
cursor.show();
// blink or not blinking of the cursor (not widely supported)
cursor.blink(true)
fn main() -> Result<()> {
execute!(stdout(), Goto(10, 10))
}
```

## Tested terminals

- Windows Powershell
- Windows 10 (pro)
- Windows CMD
- Windows 10 (pro)
- Windows 8.1 (N)
- Ubuntu Desktop Terminal
- Ubuntu 17.10
- (Arch, Manjaro) KDE Konsole
- Linux Mint
It's recommended to use the [Command API](https://crossterm-rs.github.io/crossterm/docs/command.html),
because this might replace some of the existing API in the future. It is more convenient, faster and
easier to use.

This crate supports all Unix terminals and windows terminals down to Windows 7 but not all of them have been tested.
If you have used this library for a terminal other than the above list without issues feel free to add it to the above list, I really would appreciate it.
## Other resources

- [API documentation](https://docs.rs/crossterm_cursor/) (with other examples)
- [Examples repository](https://github.com/crossterm-rs/examples)
- [The Book](https://crossterm-rs.github.io/crossterm/docs/index.html)

## Authors

* **Timon Post** - *Project Owner & creator*

## License

This project is licensed under the MIT License - see the [LICENSE.md](./LICENSE) file for details

This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details

[s1]: https://img.shields.io/crates/v/crossterm_cursor.svg
[l1]: https://crates.io/crates/crossterm_cursor
Expand Down
13 changes: 3 additions & 10 deletions src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,9 @@

use crossterm_utils::Result;

pub use self::cursor::{
cursor, BlinkOff, BlinkOn, Down, Goto, Hide, Left, ResetPos, Right, SavePos, Show,
TerminalCursor, Up,
};

mod cursor;

mod ansi_cursor;
pub(crate) mod ansi;
#[cfg(windows)]
mod winapi_cursor;
pub(crate) mod windows;

///! 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
Expand All @@ -25,7 +18,7 @@ mod winapi_cursor;
///!
///! This trait is implemented for `WinApi` (Windows specific) and `ANSI` (Unix specific),
///! so that cursor related actions can be performed on both UNIX and Windows systems.
trait ITerminalCursor: Sync + Send {
pub(crate) trait Cursor: Sync + Send {
/// Goto location (`x`, `y`) in the current terminal window.
fn goto(&self, x: u16, y: u16) -> Result<()>;
/// Get the cursor location `(x, y)` in the current terminal window.
Expand Down
54 changes: 27 additions & 27 deletions src/cursor/ansi_cursor.rs → src/cursor/ansi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,47 @@ use crossterm_utils::{csi, write_cout, Result};

use crate::sys::{get_cursor_position, show_cursor};

use super::ITerminalCursor;
use super::Cursor;

pub fn get_goto_ansi(x: u16, y: u16) -> String {
pub(crate) fn goto_csi_sequence(x: u16, y: u16) -> String {
format!(csi!("{};{}H"), y + 1, x + 1)
}

pub fn get_move_up_ansi(count: u16) -> String {
pub(crate) fn move_up_csi_sequence(count: u16) -> String {
format!(csi!("{}A"), count)
}

pub fn get_move_right_ansi(count: u16) -> String {
pub(crate) fn move_right_csi_sequence(count: u16) -> String {
format!(csi!("{}C"), count)
}

pub fn get_move_down_ansi(count: u16) -> String {
pub(crate) fn move_down_csi_sequence(count: u16) -> String {
format!(csi!("{}B"), count)
}

pub fn get_move_left_ansi(count: u16) -> String {
pub(crate) fn move_left_csi_sequence(count: u16) -> String {
format!(csi!("{}D"), count)
}

pub static SAVE_POS_ANSI: &'static str = csi!("s");
pub static RESTORE_POS_ANSI: &'static str = csi!("u");
pub static HIDE_ANSI: &'static str = csi!("?25l");
pub static SHOW_ANSI: &'static str = csi!("?25h");
pub static BLINK_ON_ANSI: &'static str = csi!("?12h");
pub static BLINK_OFF_ANSI: &'static str = csi!("?12l");
pub(crate) static SAVE_POSITION_CSI_SEQUENCE: &'static str = csi!("s");
pub(crate) static RESTORE_POSITION_CSI_SEQUENCE: &'static str = csi!("u");
pub(crate) static HIDE_CSI_SEQUENCE: &'static str = csi!("?25l");
pub(crate) static SHOW_CSI_SEQUENCE: &'static str = csi!("?25h");
pub(crate) static BLINKING_ON_CSI_SEQUENCE: &'static str = csi!("?12h");
pub(crate) static BLINKING_OFF_CSI_SEQUENCE: &'static str = csi!("?12l");

/// This struct is an ANSI implementation for cursor related actions.
pub struct AnsiCursor;
pub(crate) struct AnsiCursor;

impl AnsiCursor {
pub fn new() -> AnsiCursor {
pub(crate) fn new() -> AnsiCursor {
AnsiCursor
}
}

impl ITerminalCursor for AnsiCursor {
impl Cursor for AnsiCursor {
fn goto(&self, x: u16, y: u16) -> Result<()> {
write_cout!(get_goto_ansi(x, y))?;
write_cout!(goto_csi_sequence(x, y))?;
Ok(())
}

Expand All @@ -55,32 +55,32 @@ impl ITerminalCursor for AnsiCursor {
}

fn move_up(&self, count: u16) -> Result<()> {
write_cout!(get_move_up_ansi(count))?;
write_cout!(move_up_csi_sequence(count))?;
Ok(())
}

fn move_right(&self, count: u16) -> Result<()> {
write_cout!(get_move_right_ansi(count))?;
write_cout!(move_right_csi_sequence(count))?;
Ok(())
}

fn move_down(&self, count: u16) -> Result<()> {
write_cout!(get_move_down_ansi(count))?;
write_cout!(move_down_csi_sequence(count))?;
Ok(())
}

fn move_left(&self, count: u16) -> Result<()> {
write_cout!(get_move_left_ansi(count))?;
write_cout!(move_left_csi_sequence(count))?;
Ok(())
}

fn save_position(&self) -> Result<()> {
write_cout!(SAVE_POS_ANSI)?;
write_cout!(SAVE_POSITION_CSI_SEQUENCE)?;
Ok(())
}

fn restore_position(&self) -> Result<()> {
write_cout!(RESTORE_POS_ANSI)?;
write_cout!(RESTORE_POSITION_CSI_SEQUENCE)?;
Ok(())
}

Expand All @@ -96,22 +96,22 @@ impl ITerminalCursor for AnsiCursor {

fn blink(&self, blink: bool) -> Result<()> {
if blink {
write_cout!(BLINK_ON_ANSI)?;
write_cout!(BLINKING_ON_CSI_SEQUENCE)?;
} else {
write_cout!(BLINK_OFF_ANSI)?;
write_cout!(BLINKING_OFF_CSI_SEQUENCE)?;
}
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::{AnsiCursor, ITerminalCursor};
use super::{AnsiCursor, Cursor};

// TODO - Test is ingored, because it's stalled on Travis CI
#[test]
#[ignore]
fn test_ansi_save_restore_position() {
fn test_save_restore_position() {
if try_enable_ansi() {
let cursor = AnsiCursor::new();

Expand All @@ -131,7 +131,7 @@ mod tests {
// TODO - Test is ingored, because it's stalled on Travis CI
#[test]
#[ignore]
fn test_ansi_goto() {
fn test_goto() {
if try_enable_ansi() {
let cursor = AnsiCursor::new();

Expand Down
Loading