Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs images helper #190

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ requires an extra flag which is documented below.
```bash
RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --features "unstable" --open
```
* To generate images for documentation, run `cargo test --features "test unstable docs_images_save_png" --doc`
* `clang` will need to be installed along with the following flags:
* `RUSTDOCFLAGS = "--cfg docs_images" `
* `RUSTFLAGS = "--cfg docs_images" `
* The same flags need to be used for `RUSTDOCFLAGS` and `RUSTFLAGS` is that we need to tell rust that we want to implement the helper trait `SavePng` for a bunch of things. Then when we are running the actual doc tests need to tell rust to create the images. But as they are run seperately the flag doesn't carry over so we need to have it in both places. (note: the flag `doctests_run_user_input` is used for tests that require userinput that we don't want to run but to show in the docs)

## Adding Examples
[adding-examples]: #adding-examples
Expand Down
16 changes: 15 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ cfg-if = "0.1"

parking_lot = "0.10"


# docs_images_save_png feature
resvg = {version = "0.11.0", optional = true}
usvg = {version = "0.11.0", optional = true}

[dependencies.futures-util]
version = "0.3"
default-features = false
Expand All @@ -74,6 +79,7 @@ features = [
# a library.
[dev-dependencies]
bitvec = "0.17"
# doctest_run_user_input

# Since the debug performance of turtle isn't all that great, we recommend that
# every user of turtle add the following to their Cargo.toml
Expand All @@ -92,7 +98,7 @@ opt-level = 3

[features]
# The reason we do this is because doctests don't get cfg(test)
# See: https://github.com/rust-lang/cargo/issues/4669
# See: https://github.com/rust-lang/rust/issues/45599
#
# This allows us to write attributes like the following and have it work
# in all tests.
Expand All @@ -107,3 +113,11 @@ test = []
#
# Users of the crate must explicitly opt-in to activate them.
unstable = []

# This feature is only designed for generating images to be used for documentation. Therefore you need to
# set both RUSTFLAGS and RUSTDOCFLAGS to "--cfg docs_images" in order to generate png files when running
# the doc tests. For more information please see: CONTRIBUTING.md
# note: clang is required for resvg
# note: the flag `doctests_run_user_input` is used for tests that
# require userinput that we don't want to run but to show in the docs
docs_images_save_png = ["resvg", "usvg"]
Binary file modified docs/assets/images/docs/circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/circle_offset_center.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/clear_after_click.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/clear_before_click.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/color_mixing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/colored_circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/pen_thickness.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/red_circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/images/docs/small_drawing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
183 changes: 0 additions & 183 deletions docs/assets/images/docs/squares.svg

This file was deleted.

19 changes: 13 additions & 6 deletions src/async_drawing.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::fmt::Debug;
use std::path::Path;

use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};

use crate::ipc_protocol::ProtocolClient;
use crate::async_turtle::AsyncTurtle;
use crate::{Drawing, Point, Color, Event, ExportError};
use crate::ipc_protocol::ProtocolClient;
use crate::{Color, Drawing, Event, ExportError, Point};
JosephLing marked this conversation as resolved.
Show resolved Hide resolved

/// Represents a size
///
Expand Down Expand Up @@ -71,9 +71,8 @@ impl AsyncDrawing {
// of many programs that use the turtle crate.
crate::start();

let client = ProtocolClient::new().await
.expect("unable to create renderer client");
Self {client}
let client = ProtocolClient::new().await.expect("unable to create renderer client");
Self { client }
}

pub async fn add_turtle(&mut self) -> AsyncTurtle {
Expand Down Expand Up @@ -188,3 +187,11 @@ impl AsyncDrawing {
self.client.debug_drawing().await
}
}


#[cfg(docs_images)]
impl crate::SavePng for AsyncDrawing {
fn save_png(&self, path: &str) -> Result<(), String> {
self.client.save_png(path)
}
}
41 changes: 28 additions & 13 deletions src/async_turtle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use std::fmt::Debug;

use tokio::time;

use crate::radians::{self, Radians};
use crate::ipc_protocol::{ProtocolClient, RotationDirection};
use crate::radians::{self, Radians};
use crate::renderer_server::TurtleId;
use crate::{Turtle, Color, Point, Speed};
use crate::{Color, Point, Speed, Turtle};

/// Any distance value (positive or negative)
pub type Distance = f64;
Expand Down Expand Up @@ -58,8 +58,7 @@ impl AsyncTurtle {
// of many programs that use the turtle crate.
crate::start();

let client = ProtocolClient::new().await
.expect("unable to create renderer client");
let client = ProtocolClient::new().await.expect("unable to create renderer client");
Self::with_client(client).await
}

Expand All @@ -68,7 +67,7 @@ impl AsyncTurtle {
let id = client.create_turtle().await;
let angle_unit = AngleUnit::Degrees;

Self {client, id, angle_unit}
Self { client, id, angle_unit }
}

pub async fn forward(&mut self, distance: Distance) {
Expand All @@ -87,7 +86,9 @@ impl AsyncTurtle {

pub async fn left(&mut self, angle: Angle) {
let angle = self.angle_unit.to_radians(angle);
self.client.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise).await
self.client
.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise)
.await
}

pub async fn wait(&mut self, secs: f64) {
Expand Down Expand Up @@ -122,13 +123,13 @@ impl AsyncTurtle {
}

pub async fn set_x(&mut self, x: f64) {
let Point {x: _, y} = self.position().await;
self.go_to(Point {x, y}).await
let Point { x: _, y } = self.position().await;
self.go_to(Point { x, y }).await
}

pub async fn set_y(&mut self, y: f64) {
let Point {x, y: _} = self.position().await;
self.go_to(Point {x, y}).await
let Point { x, y: _ } = self.position().await;
self.go_to(Point { x, y }).await
}

pub async fn home(&mut self) {
Expand All @@ -155,7 +156,9 @@ impl AsyncTurtle {
// Formula from: https://stackoverflow.com/a/24234924/551904
let angle = angle - radians::TWO_PI * ((angle + radians::PI) / radians::TWO_PI).floor();

self.client.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise).await
self.client
.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise)
.await
}

pub fn is_using_degrees(&self) -> bool {
Expand Down Expand Up @@ -291,13 +294,15 @@ impl AsyncTurtle {
angle
};

self.client.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise).await
self.client
.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise)
.await
}

pub async fn wait_for_click(&mut self) {
use crate::{
event::{MouseButton::LeftButton, PressedState::Pressed},
Event::MouseButton,
event::{PressedState::Pressed, MouseButton::LeftButton},
};

loop {
Expand All @@ -324,3 +329,13 @@ impl AsyncTurtle {
self.client.debug_turtle(self.id, self.angle_unit).await
}
}

#[cfg(docs_images)]
impl crate::SavePng for AsyncTurtle {
fn save_png(&self, path: &str) -> Result<(), String> {
match self.client.save_png(path) {
Ok(()) => Ok(()),
Err(e) => Err(e.to_string()),
}
}
}
4 changes: 3 additions & 1 deletion src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,9 @@ impl Color {
///
/// Let's look at a more complete example to really show what happens when we're mixing colors together.
///
/// ```no_run
/// ```
/// use turtle::{Color, Drawing};
/// # #[cfg(docs_images)] use crate::turtle::SavePng;
///
/// fn main() {
/// let mut drawing = Drawing::new();
Expand Down Expand Up @@ -525,6 +526,7 @@ impl Color {
/// turtle.set_pen_color(red.mix("blue", 0.75));
/// turtle.forward(100.0);
/// turtle.right(90.0);
/// # #[cfg(docs_images)] drawing.save_png("color_mixing").unwrap();
/// }
/// ```
///
Expand Down
43 changes: 31 additions & 12 deletions src/drawing.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::fmt::{self, Debug};
use std::path::Path;

use crate::{Turtle, Color, Point, Size, ExportError};
use crate::async_drawing::AsyncDrawing;
use crate::sync_runtime::block_on;
use crate::{Color, ExportError, Point, Size, Turtle};

/// Provides access to properties of the drawing that the turtle is creating
///
Expand Down Expand Up @@ -70,7 +70,7 @@ impl From<AsyncDrawing> for Drawing {
fn from(drawing: AsyncDrawing) -> Self {
//TODO: There is no way to set `turtles` properly here, but that's okay since it is going
// to be removed soon.
Self {drawing, turtles: 1}
Self { drawing, turtles: 1 }
}
}

Expand Down Expand Up @@ -149,14 +149,15 @@ impl Drawing {
///
/// # Example
///
/// ```rust,no_run
/// ```rust
/// use turtle::Drawing;
///
/// fn main() {
/// let mut drawing = Drawing::new();
/// # #[allow(unused)] // Good to show turtle creation here even if unused
/// let mut turtle = drawing.add_turtle();
/// drawing.set_title("My Fancy Title! - Yay!");
///
/// }
/// ```
///
Expand Down Expand Up @@ -188,7 +189,7 @@ impl Drawing {
///
/// # Example
///
/// ```rust,no_run
/// ```rust
/// use turtle::Drawing;
///
/// fn main() {
Expand Down Expand Up @@ -230,8 +231,9 @@ impl Drawing {
///
/// # Example
///
/// ```rust,no_run
/// ```rust
/// use turtle::Drawing;
/// # #[cfg(docs_images)] use crate::turtle::SavePng;
///
/// fn main() {
/// let mut drawing = Drawing::new();
Expand All @@ -243,9 +245,11 @@ impl Drawing {
/// // Rotate to the right (clockwise) by 1 degree
/// turtle.right(1.0);
/// }
///
/// # #[cfg(docs_images)] drawing.save_png("circle").unwrap();
/// # #[cfg(doctests_run_user_input)]
/// turtle.wait_for_click();
/// drawing.set_center([50.0, 100.0]);
/// # #[cfg(docs_images)] drawing.save_png("circle_offset_center").unwrap();
/// }
/// ```
///
Expand Down Expand Up @@ -313,9 +317,10 @@ impl Drawing {
///
/// # Example
///
/// ```rust,no_run
/// ```rust
/// use turtle::Drawing;
///
///
/// # #[cfg(docs_images)] use crate::turtle::SavePng;
/// fn main() {
/// let mut drawing = Drawing::new();
/// let mut turtle = drawing.add_turtle();
Expand All @@ -326,9 +331,11 @@ impl Drawing {
/// // Rotate to the right (clockwise) by 1 degree
/// turtle.right(1.0);
/// }
///
/// # #[cfg(docs_images)] drawing.save_png("drawing").unwrap();
/// # #[cfg(doctest_run_user_input)]
/// turtle.wait_for_click();
/// drawing.set_size((300, 300));
/// # #[cfg(docs_images)] drawing.save_png("small_drawing").unwrap();
/// }
/// ```
///
Expand Down Expand Up @@ -585,7 +592,7 @@ impl Drawing {

/// Saves the current drawings in SVG format at the location specified by `path`.
///
/// ```rust,no_run
/// ```rust
/// use turtle::{Drawing, Turtle, Color, ExportError};
///
/// fn main() -> Result<(), ExportError> {
Expand Down Expand Up @@ -629,12 +636,24 @@ impl Drawing {
}
}

#[cfg(docs_images)]
impl crate::SavePng for Drawing {
fn save_png(&self, path: &str) -> Result<(), String> {
match block_on(self.drawing.save_svg(Path::new(path))) {
Ok(()) => Ok(()),
Err(e) => Err(e.to_string()),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
#[should_panic(expected = "Invalid color: Color { red: NaN, green: 0.0, blue: 0.0, alpha: 0.0 }. See the color module documentation for more information.")]
#[should_panic(
expected = "Invalid color: Color { red: NaN, green: 0.0, blue: 0.0, alpha: 0.0 }. See the color module documentation for more information."
)]
fn rejects_invalid_background_color() {
let mut drawing = Drawing::new();
drawing.set_background_color(Color {
Expand All @@ -655,7 +674,7 @@ mod tests {

#[test]
fn ignores_center_nan_inf() {
let center = Point {x: 5.0, y: 10.0};
let center = Point { x: 5.0, y: 10.0 };

let mut drawing = Drawing::new();
drawing.set_center(center);
Expand Down
Loading