diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ffddff..814510c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,29 +1,63 @@ on: pull_request -name: Continuous integration +name: Continuous Integration + +env: + RUSTFLAGS: -D warnings jobs: ci: - runs-on: ${{ matrix.os }} + name: ${{ matrix.target.name }} [${{ matrix.rust_version }}] + runs-on: ${{ matrix.target.os }} strategy: + fail-fast: false matrix: - rust: - - stable - os: [ubuntu-latest, windows-latest] + rust_version: ["stable", "1.62.1"] + target: + - name: Linux + os: ubuntu-latest + extra_flags: --all-features + run_tests: true + + - name: Linux (no-std) + os: ubuntu-latest + extra_flags: --no-default-features + run_tests: true + + - name: Windows + os: windows-latest + extra_flags: --all-features + run_tests: true + + - name: Windows (no-std) + os: windows-latest + extra_flags: --no-default-features + run_tests: true + + - name: Bare Metal (no-std) + os: ubuntu-latest + extra_flags: --no-default-features + run_tests: false + env: + TARGET: thumbv7em-none-eabihf + steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: - toolchain: ${{ matrix.rust }} - components: rustfmt, clippy + targets: ${{ matrix.target.env.TARGET || '' }} + toolchain: ${{ matrix.rust_version }} + components: clippy, rustfmt - run: cargo fmt --check --all - - run: cargo clippy -- -D warnings - - run: cargo build --all-features - - run: cargo test - - run: cargo test --all-features - - run: cargo run --example 256_colors - - run: cargo run --example hyperlink - - run: cargo run --example title + - run: cargo clippy ${{ matrix.target.extra_flags }} + - run: cargo build ${{ matrix.target.extra_flags }} + + - if: matrix.target.run_tests + run: | + cargo test ${{ matrix.target.extra_flags }} + cargo run ${{ matrix.target.extra_flags }} --example 256_colors + cargo run ${{ matrix.target.extra_flags }} --example hyperlink + cargo run ${{ matrix.target.extra_flags }} --example title diff --git a/.gitignore b/.gitignore index 601dd57..99acbeb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ target -Cargo.lock # JetBrains' IDE items .idea/* diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6ede8e6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,195 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "nu-ansi-term" +version = "0.50.2" +dependencies = [ + "doc-comment", + "serde", + "serde_json", + "windows-sys", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.227" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80ece43fc6fbed4eb5392ab50c07334d3e577cbf40997ee896fe7af40bba4245" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.227" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a576275b607a2c86ea29e410193df32bc680303c82f31e275bbfcafe8b33be5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.227" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e694923b8824cf0e9b382adf0f60d4e05f348f357b38833a3fa5ed7c2ede04" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" diff --git a/Cargo.toml b/Cargo.toml index 0703d17..12ab914 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,8 @@ repository = "https://github.com/nushell/nu-ansi-term" doctest = true [features] +default = ["std"] +std = [] derive_serde_style = ["serde"] gnu_legacy = [] diff --git a/examples/256_colors.rs b/examples/256_colors.rs index d64ece8..09b41e5 100644 --- a/examples/256_colors.rs +++ b/examples/256_colors.rs @@ -9,7 +9,7 @@ use nu_ansi_term::Color; // - 232 to 255 are shades of grey. fn main() { - #[cfg(windows)] + #[cfg(all(windows, feature = "std"))] nu_ansi_term::enable_ansi_support().unwrap(); // First two lines diff --git a/examples/basic_colors.rs b/examples/basic_colors.rs index a446a19..d86adcc 100644 --- a/examples/basic_colors.rs +++ b/examples/basic_colors.rs @@ -3,7 +3,7 @@ use nu_ansi_term::{Color::*, Style}; // This example prints out the 16 basic colors. fn main() { - #[cfg(windows)] + #[cfg(all(windows, feature = "std"))] nu_ansi_term::enable_ansi_support().unwrap(); let normal = Style::default(); diff --git a/examples/gradient_colors.rs b/examples/gradient_colors.rs index 7ca2bbb..57e06e1 100644 --- a/examples/gradient_colors.rs +++ b/examples/gradient_colors.rs @@ -1,7 +1,7 @@ use nu_ansi_term::{build_all_gradient_text, Color, Gradient, Rgb, TargetGround}; fn main() { - #[cfg(windows)] + #[cfg(all(windows, feature = "std"))] nu_ansi_term::enable_ansi_support().unwrap(); let text = "lorem ipsum quia dolor sit amet, consectetur, adipisci velit"; diff --git a/examples/hyperlink.rs b/examples/hyperlink.rs index abb284c..34d3286 100644 --- a/examples/hyperlink.rs +++ b/examples/hyperlink.rs @@ -3,7 +3,7 @@ mod may_sleep; use may_sleep::{parse_cmd_args, sleep}; fn main() { - #[cfg(windows)] + #[cfg(all(windows, feature = "std"))] nu_ansi_term::enable_ansi_support().unwrap(); let sleep_ms = parse_cmd_args(); diff --git a/examples/rgb_colors.rs b/examples/rgb_colors.rs index 3c64d96..dc37274 100644 --- a/examples/rgb_colors.rs +++ b/examples/rgb_colors.rs @@ -8,7 +8,7 @@ const WIDTH: i32 = 80; const HEIGHT: i32 = 24; fn main() { - #[cfg(windows)] + #[cfg(all(windows, feature = "std"))] nu_ansi_term::enable_ansi_support().unwrap(); for row in 0..HEIGHT { diff --git a/examples/title.rs b/examples/title.rs index c043d87..ca8a3df 100644 --- a/examples/title.rs +++ b/examples/title.rs @@ -3,7 +3,7 @@ mod may_sleep; use may_sleep::{parse_cmd_args, sleep}; fn main() { - #[cfg(windows)] + #[cfg(all(windows, feature = "std"))] nu_ansi_term::enable_ansi_support().unwrap(); let sleep_ms = parse_cmd_args(); diff --git a/src/ansi.rs b/src/ansi.rs index 6f46dee..1302ad9 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -1,7 +1,7 @@ #![allow(missing_docs)] use crate::style::{Color, Style}; use crate::write::AnyWrite; -use std::fmt; +use core::fmt; impl Style { /// Write any bytes that go *before* a piece of text to the given writer. @@ -400,6 +400,7 @@ impl fmt::Display for Suffix { } #[cfg(test)] +#[allow(unused)] macro_rules! test { ($name: ident: $style: expr; $input: expr => $result: expr) => { #[test] @@ -414,8 +415,9 @@ macro_rules! test { } #[cfg(test)] -#[cfg(not(feature = "gnu_legacy"))] +#[cfg(all(not(feature = "gnu_legacy"), feature = "std"))] mod test { + use crate::style::Color::*; use crate::style::Style; use crate::Color; diff --git a/src/debug.rs b/src/debug.rs index 6997bab..521f059 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,5 +1,5 @@ use crate::style::Style; -use std::fmt; +use core::fmt; /// Styles have a special `Debug` implementation that only shows the fields that /// are set. Fields that haven’t been touched aren’t included in the output. diff --git a/src/display.rs b/src/display.rs index cfc1aec..030c90a 100644 --- a/src/display.rs +++ b/src/display.rs @@ -2,9 +2,8 @@ use crate::ansi::RESET; use crate::difference::Difference; use crate::style::{Color, Style}; use crate::write::AnyWrite; -use std::borrow::Cow; -use std::fmt; -use std::io; +use alloc::borrow::{Cow, ToOwned}; +use core::fmt; #[derive(Eq, PartialEq, Debug)] enum OSControl<'a, S: 'a + ToOwned + ?Sized> @@ -282,11 +281,12 @@ impl<'a> fmt::Display for AnsiString<'a> { } } +#[cfg(feature = "std")] impl<'a> AnsiByteString<'a> { /// Write an `AnsiByteString` to an `io::Write`. This writes the escape /// sequences for the associated `Style` around the bytes. - pub fn write_to(&self, w: &mut W) -> io::Result<()> { - let w: &mut dyn io::Write = w; + pub fn write_to(&self, w: &mut W) -> std::io::Result<()> { + let w: &mut dyn std::io::Write = w; self.write_to_any(w) } } @@ -331,12 +331,13 @@ impl<'a> fmt::Display for AnsiStrings<'a> { } } +#[cfg(feature = "std")] impl<'a> AnsiByteStrings<'a> { /// Write `AnsiByteStrings` to an `io::Write`. This writes the minimal /// escape sequences for the associated `Style`s around each set of /// bytes. - pub fn write_to(&self, w: &mut W) -> io::Result<()> { - let w: &mut dyn io::Write = w; + pub fn write_to(&self, w: &mut W) -> std::io::Result<()> { + let w: &mut dyn std::io::Write = w; self.write_to_any(w) } } diff --git a/src/gradient.rs b/src/gradient.rs index 00f5636..3c5dead 100644 --- a/src/gradient.rs +++ b/src/gradient.rs @@ -1,4 +1,5 @@ use crate::{rgb::Rgb, Color}; +use alloc::{format, string::String}; /// Linear color gradient between two color stops #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/src/lib.rs b/src/lib.rs index 734d122..0c81a8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,7 +181,8 @@ //! it does provide a method [`write_to`] to write the result to any value that //! implements [`Write`]: //! -//! ``` +#![cfg_attr(feature = "std", doc = "```")] +#![cfg_attr(not(feature = "std"), doc = "```ignore")] //! use nu_ansi_term::Color::Green; //! //! Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap(); @@ -190,7 +191,8 @@ //! Similarly, the type [`AnsiByteStrings`] supports writing a list of //! [`AnsiByteString`] values with minimal escape sequences: //! -//! ``` +#![cfg_attr(feature = "std", doc = "```")] +#![cfg_attr(not(feature = "std"), doc = "```ignore")] //! use nu_ansi_term::Color::Green; //! use nu_ansi_term::AnsiByteStrings; //! @@ -229,6 +231,7 @@ //! [`fg`]: struct.Style.html#method.fg //! [`on`]: struct.Style.html#method.on +#![cfg_attr(not(any(test, feature = "std")), no_std)] #![crate_name = "nu_ansi_term"] #![crate_type = "rlib"] #![warn(missing_copy_implementations)] @@ -239,6 +242,8 @@ #[cfg(test)] doc_comment::doctest!("../README.md"); +extern crate alloc; + pub mod ansi; pub use ansi::{Infix, Prefix, Suffix}; @@ -251,8 +256,9 @@ pub use display::*; mod write; +#[cfg(all(windows, feature = "std"))] mod windows; -#[allow(unused_imports)] +#[cfg(all(windows, feature = "std"))] pub use crate::windows::*; mod util; diff --git a/src/rgb.rs b/src/rgb.rs index 7faf2ab..1e41944 100644 --- a/src/rgb.rs +++ b/src/rgb.rs @@ -1,3 +1,5 @@ +use alloc::{format, string::String}; + // Code liberally borrowed from here // https://github.com/navierr/coloriz #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -149,7 +151,7 @@ const fn rgb_negate(rgb: &Rgb) -> Rgb { Rgb::new(255 - rgb.r, 255 - rgb.g, 255 - rgb.b) } -impl std::ops::Add for Rgb { +impl core::ops::Add for Rgb { type Output = Rgb; fn add(self, rhs: Rgb) -> Self::Output { @@ -157,7 +159,7 @@ impl std::ops::Add for Rgb { } } -impl std::ops::Add<&Rgb> for Rgb { +impl core::ops::Add<&Rgb> for Rgb { type Output = Rgb; fn add(self, rhs: &Rgb) -> Self::Output { @@ -165,7 +167,7 @@ impl std::ops::Add<&Rgb> for Rgb { } } -impl std::ops::Add for &Rgb { +impl core::ops::Add for &Rgb { type Output = Rgb; fn add(self, rhs: Rgb) -> Self::Output { @@ -173,7 +175,7 @@ impl std::ops::Add for &Rgb { } } -impl std::ops::Add<&Rgb> for &Rgb { +impl core::ops::Add<&Rgb> for &Rgb { type Output = Rgb; fn add(self, rhs: &Rgb) -> Self::Output { @@ -181,7 +183,7 @@ impl std::ops::Add<&Rgb> for &Rgb { } } -impl std::ops::Sub for Rgb { +impl core::ops::Sub for Rgb { type Output = Rgb; fn sub(self, rhs: Rgb) -> Self::Output { @@ -189,7 +191,7 @@ impl std::ops::Sub for Rgb { } } -impl std::ops::Sub<&Rgb> for Rgb { +impl core::ops::Sub<&Rgb> for Rgb { type Output = Rgb; fn sub(self, rhs: &Rgb) -> Self::Output { @@ -197,7 +199,7 @@ impl std::ops::Sub<&Rgb> for Rgb { } } -impl std::ops::Sub for &Rgb { +impl core::ops::Sub for &Rgb { type Output = Rgb; fn sub(self, rhs: Rgb) -> Self::Output { @@ -205,7 +207,7 @@ impl std::ops::Sub for &Rgb { } } -impl std::ops::Sub<&Rgb> for &Rgb { +impl core::ops::Sub<&Rgb> for &Rgb { type Output = Rgb; fn sub(self, rhs: &Rgb) -> Self::Output { @@ -213,7 +215,7 @@ impl std::ops::Sub<&Rgb> for &Rgb { } } -impl std::ops::Mul for Rgb { +impl core::ops::Mul for Rgb { type Output = Rgb; fn mul(self, rhs: f32) -> Self::Output { @@ -221,7 +223,7 @@ impl std::ops::Mul for Rgb { } } -impl std::ops::Mul<&f32> for Rgb { +impl core::ops::Mul<&f32> for Rgb { type Output = Rgb; fn mul(self, rhs: &f32) -> Self::Output { @@ -229,7 +231,7 @@ impl std::ops::Mul<&f32> for Rgb { } } -impl std::ops::Mul for &Rgb { +impl core::ops::Mul for &Rgb { type Output = Rgb; fn mul(self, rhs: f32) -> Self::Output { @@ -237,7 +239,7 @@ impl std::ops::Mul for &Rgb { } } -impl std::ops::Mul<&f32> for &Rgb { +impl core::ops::Mul<&f32> for &Rgb { type Output = Rgb; fn mul(self, rhs: &f32) -> Self::Output { @@ -245,7 +247,7 @@ impl std::ops::Mul<&f32> for &Rgb { } } -impl std::ops::Mul for f32 { +impl core::ops::Mul for f32 { type Output = Rgb; fn mul(self, rhs: Rgb) -> Self::Output { @@ -253,7 +255,7 @@ impl std::ops::Mul for f32 { } } -impl std::ops::Mul<&Rgb> for f32 { +impl core::ops::Mul<&Rgb> for f32 { type Output = Rgb; fn mul(self, rhs: &Rgb) -> Self::Output { @@ -261,7 +263,7 @@ impl std::ops::Mul<&Rgb> for f32 { } } -impl std::ops::Mul for &f32 { +impl core::ops::Mul for &f32 { type Output = Rgb; fn mul(self, rhs: Rgb) -> Self::Output { @@ -269,7 +271,7 @@ impl std::ops::Mul for &f32 { } } -impl std::ops::Mul<&Rgb> for &f32 { +impl core::ops::Mul<&Rgb> for &f32 { type Output = Rgb; fn mul(self, rhs: &Rgb) -> Self::Output { @@ -277,7 +279,7 @@ impl std::ops::Mul<&Rgb> for &f32 { } } -impl std::ops::Neg for Rgb { +impl core::ops::Neg for Rgb { type Output = Rgb; fn neg(self) -> Self::Output { @@ -285,7 +287,7 @@ impl std::ops::Neg for Rgb { } } -impl std::ops::Neg for &Rgb { +impl core::ops::Neg for &Rgb { type Output = Rgb; fn neg(self) -> Self::Output { diff --git a/src/util.rs b/src/util.rs index f1ed36f..ae1f1bf 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,6 @@ use crate::display::{AnsiString, AnsiStrings}; -use std::ops::Deref; +use alloc::{string::String, vec::Vec}; +use core::ops::Deref; /// Return a substring of the given AnsiStrings sequence, while keeping the formatting. pub fn sub_string(start: usize, len: usize, strs: &AnsiStrings) -> Vec> { diff --git a/src/write.rs b/src/write.rs index 5527719..486fc9f 100644 --- a/src/write.rs +++ b/src/write.rs @@ -1,5 +1,4 @@ -use std::fmt; -use std::io; +use core::fmt; pub trait AnyWrite { type Wstr: ?Sized; @@ -23,15 +22,16 @@ impl<'a> AnyWrite for dyn fmt::Write + 'a { } } -impl<'a> AnyWrite for dyn io::Write + 'a { +#[cfg(feature = "std")] +impl<'a> AnyWrite for dyn std::io::Write + 'a { type Wstr = [u8]; - type Error = io::Error; + type Error = std::io::Error; fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> { - io::Write::write_fmt(self, fmt) + std::io::Write::write_fmt(self, fmt) } fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> { - io::Write::write_all(self, s) + std::io::Write::write_all(self, s) } }