Merge pull request #4 from sgoudham/v0.2.0

pull/8/head
Hamothy 3 years ago committed by GitHub
commit 782705852a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -47,8 +47,11 @@ jobs:
7z a "${{ env.BIN }}.zip" "${{ env.BIN }}.exe" 7z a "${{ env.BIN }}.zip" "${{ env.BIN }}.exe"
mv "${{ env.BIN }}.zip" $GITHUB_WORKSPACE mv "${{ env.BIN }}.zip" $GITHUB_WORKSPACE
shell: bash shell: bash
# We're using a fork of `actions/create-release` that detects - name: "Build Changelog"
# whether a release is already available or not first. id: build_changelog
uses: mikepenz/release-changelog-builder-action@{latest-release}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: XAMPPRocky/create-release@v1.0.2 - uses: XAMPPRocky/create-release@v1.0.2
id: create_release id: create_release
env: env:
@ -56,8 +59,7 @@ jobs:
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
release_name: ${{ github.ref }} release_name: ${{ github.ref }}
# Draft should **always** be false. GitHub doesn't provide a way to body: ${{steps.github_release.outputs.changelog}}
# get draft releases from its API, so there's no point using it.
draft: false draft: false
prerelease: false prerelease: false
- uses: actions/upload-release-asset@v1 - uses: actions/upload-release-asset@v1
@ -88,6 +90,11 @@ jobs:
- run: scripts/set_rust_version.bash stable ${{ matrix.target }} - run: scripts/set_rust_version.bash stable ${{ matrix.target }}
- run: scripts/build.bash cross ${{ matrix.target }} RELEASE - run: scripts/build.bash cross ${{ matrix.target }} RELEASE
- run: tar -czvf ${{ env.BIN }}.tar.gz --directory=target/${{ matrix.target }}/release ${{ env.BIN }} - run: tar -czvf ${{ env.BIN }}.tar.gz --directory=target/${{ matrix.target }}/release ${{ env.BIN }}
- name: "Build Changelog"
id: build_changelog
uses: mikepenz/release-changelog-builder-action@{latest-release}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: XAMPPRocky/create-release@v1.0.2 - uses: XAMPPRocky/create-release@v1.0.2
id: create_release id: create_release
env: env:
@ -95,6 +102,7 @@ jobs:
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
release_name: ${{ github.ref }} release_name: ${{ github.ref }}
body: ${{steps.github_release.outputs.changelog}}
draft: false draft: false
prerelease: false prerelease: false
- uses: actions/upload-release-asset@v1 - uses: actions/upload-release-asset@v1
@ -106,6 +114,18 @@ jobs:
asset_path: ${{ env.BIN }}.tar.gz asset_path: ${{ env.BIN }}.tar.gz
asset_name: ${{ env.BIN }}-${{ matrix.target }}.tar.gz asset_name: ${{ env.BIN }}-${{ matrix.target }}.tar.gz
asset_content_type: application/gzip asset_content_type: application/gzip
- uses: mislav/bump-homebrew-formula-action@v1
if: "!contains(github.ref, '-')" # skip prereleases
with:
formula-name: ${{ env.BIN }}
homebrew-tap: sgoudham/tap
download-url: https://github.com/sgoudham/${{ env.BIN }}/releases/download/${{ github.ref }}/${{ env.BIN }}-${{ matrix.target }}.tar.gz
commit-message: |
{{formulaName}} {{version}}
Created by https://github.com/mislav/bump-homebrew-formula-action
env:
COMMITTER_TOKEN: ${{ secrets.HOMEBREW }}
linux: linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -126,6 +146,11 @@ jobs:
- run: scripts/set_rust_version.bash stable ${{ matrix.target }} - run: scripts/set_rust_version.bash stable ${{ matrix.target }}
- run: scripts/build.bash /tmp/cross ${{ matrix.target }} RELEASE - run: scripts/build.bash /tmp/cross ${{ matrix.target }} RELEASE
- run: tar -czvf ${{ env.BIN }}.tar.gz --directory=target/${{ matrix.target }}/release ${{ env.BIN }} - run: tar -czvf ${{ env.BIN }}.tar.gz --directory=target/${{ matrix.target }}/release ${{ env.BIN }}
- name: "Build Changelog"
id: build_changelog
uses: mikepenz/release-changelog-builder-action@{latest-release}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: XAMPPRocky/create-release@v1.0.2 - uses: XAMPPRocky/create-release@v1.0.2
id: create_release id: create_release
env: env:
@ -133,6 +158,7 @@ jobs:
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
release_name: ${{ github.ref }} release_name: ${{ github.ref }}
body: ${{steps.github_release.outputs.changelog}}
draft: false draft: false
prerelease: false prerelease: false
- name: Upload Release Asset - name: Upload Release Asset
@ -145,3 +171,25 @@ jobs:
asset_path: ${{ env.BIN }}.tar.gz asset_path: ${{ env.BIN }}.tar.gz
asset_name: ${{ env.BIN }}-${{ matrix.target }}.tar.gz asset_name: ${{ env.BIN }}-${{ matrix.target }}.tar.gz
asset_content_type: application/gzip asset_content_type: application/gzip
homebrew:
name: Bump Homebrew formula
needs: macos
runs-on: ubuntu-latest
steps:
- name: Extract version
id: extract-version
run: |
printf "::set-output name=%s::%s\n" tag-name "${GITHUB_REF#refs/tags/}"
- uses: mislav/bump-homebrew-formula-action@v1
if: "!contains(github.ref, '-')" # skip prereleases
with:
formula-name: ${{ env.BIN }}
formula-path: Formula/${{ env.BIN }}.rb
homebrew-tap: sgoudham/tap
download-url: https://github.com/sgoudham/${{ env.BIN }}/releases/download/${{ github.ref }}/${{ env.BIN }}-${{ matrix.target }}.tar.gz
commit-message: |
{{formulaName}} {{version}}
Created by https://github.com/mislav/bump-homebrew-formula-action
env:
COMMITTER_TOKEN: ${{ secrets.HOMEBREW }}

@ -1,19 +1,21 @@
[package] [package]
name = "uwuifyy" name = "uwuifyy"
version = "0.1.1" version = "0.2.0"
edition = "2021" edition = "2021"
authors = ["Goudham <sgoudham@gmail.com>"] authors = ["Goudham <sgoudham@gmail.com>"]
description = "A robust, customizable, efficient and easy-to-use command line application to uwu'ify your text!" description = "A robust, customizable, blazingly-fast, efficient and easy-to-use command line application to uwu'ify your text!"
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
repository = "https://github.com/sgoudham/uwuifyy" repository = "https://github.com/sgoudham/uwuifyy"
keywords = ["cli", "uwu", "owo", "uwuify", "anime"] keywords = ["cli", "uwu", "owo", "uwuify", "anime"]
categories = ["command-line-utilities"] categories = ["command-line-utilities"]
exclude = [ exclude = [
"examples/the-complete-works-of-william-shakespeare.txt", "examples/the-complete-works-of-william-shakespeare.txt",
"examples/tiktok_app_reviews.csv", "examples/tiktok_app_reviews.csv",
"examples/tokyo-2020-olympics-tweets.csv", "examples/tokyo-2020-olympics-tweets.csv",
"examples/uwu/**", "examples/uwu/**",
".github/**",
"scripts/**"
] ]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -27,6 +29,7 @@ rand = "0.8.4"
indicatif = "0.16.2" indicatif = "0.16.2"
linkify = "0.8.0" linkify = "0.8.0"
rand_xoshiro = "0.6.0" rand_xoshiro = "0.6.0"
ahash = "0.7.6"
memmap = "0.7.0" memmap = "0.7.0"
[profile.release] [profile.release]

@ -5,9 +5,9 @@
[![downloads](https://img.shields.io/crates/d/uwuifyy)](https://crates.io/crates/uwuifyy) [![downloads](https://img.shields.io/crates/d/uwuifyy)](https://crates.io/crates/uwuifyy)
[![license](https://img.shields.io/github/license/sgoudham/uwuifyy)](LICENSE) [![license](https://img.shields.io/github/license/sgoudham/uwuifyy)](LICENSE)
> A robust, customizable, efficient and easy-to-use command line application to uwu'ify your text! > A robust, customizable, blazingly-fast, efficient and easy-to-use command line application to uwu'ify your text!
> >
![](logo/UwUifyy-Transparent-Small.png) ![](logo/uwuifyy-logo.png)
> >
> Logo Credits: Jade Nelson > Logo Credits: Jade Nelson
@ -17,9 +17,11 @@
* [About](#about) * [About](#about)
* [Features](#features) * [Features](#features)
* [Installation](#installation) * [Installation](#installation)
+ [Windows](#windows) * [Homebrew](#homebrew)
+ [Linux \ macOS](#Linux-\-macOS) * [Binaries](#binaries)
+ [Rust \ Cargo](#Rust-\-Cargo) + [Windows](#windows)
+ [Linux \ macOS](#Linux-\-macOS)
+ [Rust \ Cargo](#Rust-\-Cargo)
* [Usage](#usage) * [Usage](#usage)
+ [Text Input to Text Output](#text-input-to-text-output) + [Text Input to Text Output](#text-input-to-text-output)
+ [Text Input to File Output](#text-input-to-file-output) + [Text Input to File Output](#text-input-to-file-output)
@ -40,6 +42,7 @@ allows you to _uwu'ify_ text and files from within your own terminal in an _extr
## Features ## Features
- [x] _**BLAZINGLY FAST**_ (Check out -> [Benchmarks](#benchmarks))
- [x] Seeded by default to allow for reproducible results - [x] Seeded by default to allow for reproducible results
- [x] Excludes URL's & Emails - [x] Excludes URL's & Emails
- [x] UwU'ify files available locally on disk - [x] UwU'ify files available locally on disk
@ -47,6 +50,17 @@ allows you to _uwu'ify_ text and files from within your own terminal in an _extr
## Installation ## Installation
### Homebrew
For `macOS` users, installation through [Homebrew](https://brew.sh/) is recommended.
```shell
$ brew tap sgoudham/tap
$ brew install uwuifyy
```
### Binaries
Binaries for **Windows**, **macOS** & **Linux** are available with every Binaries for **Windows**, **macOS** & **Linux** are available with every
single [release](https://github.com/sgoudham/uwuifyy/releases) single [release](https://github.com/sgoudham/uwuifyy/releases)
@ -69,13 +83,13 @@ C:
3. Set `uwuifyy.exe` in your path to access it globally 3. Set `uwuifyy.exe` in your path to access it globally
```shell ```shell
setx path "%path%;C:\your\path\here\bin" $ setx path "%path%;C:\your\path\here\bin"
``` ```
4. Refresh command line and verify installation 4. Refresh command line and verify installation
```shell ```shell
uwuifyy --help $ uwuifyy --help
``` ```
### Linux \ macOS ### Linux \ macOS
@ -88,43 +102,44 @@ uwuifyy --help
```shell ```shell
# Linux # Linux
tar -xf uwuifyy-x86_64-unknown-linux-gnu.tar.gz $ tar -xf uwuifyy-x86_64-unknown-linux-gnu.tar.gz
tar -xf uwuifyy-x86_64-unknown-linux-musl.tar.gz $ tar -xf uwuifyy-x86_64-unknown-linux-musl.tar.gz
# macOS # macOS
tar -xf uwuifyy-x86_64-apple-darwin.tar.gz $ tar -xf uwuifyy-x86_64-apple-darwin.tar.gz
``` ```
3. Move into `~/bin` 3. Move into `~/bin`
```shell ```shell
# Create ~/bin if it does not exist # Create ~/bin if it does not exist
mkdir -p ~/bin $ mkdir -p ~/bin
mv uwuifyy ~/bin $ mv uwuifyy ~/bin
``` ```
4. Set permissions for executable 4. Set permissions for executable
```shell ```shell
chmod 755 ~/bin/uwuifyy $ chmod 755 ~/bin/uwuifyy
``` ```
5. Update `PATH` to use globally 5. Update `PATH` to use globally
```shell ```shell
# Linux # Linux
echo 'export PATH=~/bin:$PATH' >> ~/.bashrc $ echo 'export PATH=~/bin:$PATH' >> ~/.bashrc
source ~/.bashrc $ source ~/.bashrc
# macOS # macOS
echo 'export PATH=~/bin:$PATH' >> ~/.bash_profile $ echo 'export PATH=~/bin:$PATH' >> ~/.bash_profile
source ~/.bash_profile $ source ~/.bash_profile
``` ```
6. Verify installation 6. Verify installation
```shell ```shell
uwuifyy --help $ uwuifyy --help
uwuifyy 0.2.0
``` ```
### Rust \ Cargo ### Rust \ Cargo
@ -132,7 +147,7 @@ uwuifyy --help
Alternatively, if using Rust's package manager, `Cargo`, all that is needed is Alternatively, if using Rust's package manager, `Cargo`, all that is needed is
```shell ```shell
cargo install uwuifyy $ cargo install uwuifyy
``` ```
If you do not have `Cargo` available on your machine, you can download it as part of If you do not have `Cargo` available on your machine, you can download it as part of
@ -141,6 +156,8 @@ Rust [here](https://www.rust-lang.org/tools/install)
## Usage ## Usage
```commandline ```commandline
$ uwuifyy --help
USAGE: USAGE:
uwuifyy.exe [OPTIONS] <--text <TEXT>|--infile <FILE>> uwuifyy.exe [OPTIONS] <--text <TEXT>|--infile <FILE>>
@ -159,42 +176,15 @@ OPTIONS:
### Text Input to Text Output ### Text Input to Text Output
```shell ![](examples/gifs/text-input-to-text-output.gif)
uwuifyy --text "According to all known laws of aviation, there is no way a bee should be able to fly."
Accowding to aww knyown waws of aviation, thewe xDD is nyo way :3 a bee shouwd be abwe to *screams* fwy.
```
### Text Input to File Output ### Text Input to File Output
```shell ![](examples/gifs/text-input-to-file-output.gif)
uwuifyy --text "According to all known laws of aviation, there is no way a bee should be able to fly." --outfile your/path/here/outfile.txt
[00:00:00] [############################################################] 104B/104B (0s) UwU'ifying Complete!
```
```text
your/path/here/outfile.txt
-------------------------------------
Accowding to aww knyown waws of aviation, thewe xDD is nyo way :3 a bee shouwd be abwe to *screams* fwy.
```
### File Input to File Output ### File Input to File Output
```text ![](examples/gifs/text-file-to-file-output.gif)
your/path/here/infile.txt
-------------------------------------
According to all known laws of aviation, there is no way a bee should be able to fly.
```
```shell
uwuifyy --infile your/path/here/infile.txt --outfile your/path/here/outfile.txt
[00:00:00] [############################################################] 85B/85B (0s) UwU'ifying Complete!
```
```text
your/path/here/outfile.txt
-------------------------------------
Accowding to aww knyown waws of aviation, thewe xDD is nyo way :3 a bee shouwd be abwe to *screams* fwy.
```
## Benchmarks ## Benchmarks
@ -206,7 +196,7 @@ Accowding to aww knyown waws of aviation, thewe xDD is nyo way :3 a bee shouwd b
- [Dataset](https://www.kaggle.com/kewagbln/shakespeareonline) - [Dataset](https://www.kaggle.com/kewagbln/shakespeareonline)
- Size: `5.46 MiB` - Size: `5.46 MiB`
- Time Taken: `1s` - Time Taken: `< 1s`
![](examples/gifs/william-shakespeare.gif) ![](examples/gifs/william-shakespeare.gif)
@ -214,7 +204,7 @@ Accowding to aww knyown waws of aviation, thewe xDD is nyo way :3 a bee shouwd b
- [Dataset](https://www.kaggle.com/amritpal333/tokyo-olympics-2021-tweets) - [Dataset](https://www.kaggle.com/amritpal333/tokyo-olympics-2021-tweets)
- Size: `98.54 MiB` - Size: `98.54 MiB`
- Time Taken: `8s` - Time Taken: `1s`
![](examples/gifs/tokyo-2020-olympics-tweets.gif) ![](examples/gifs/tokyo-2020-olympics-tweets.gif)
@ -222,7 +212,7 @@ Accowding to aww knyown waws of aviation, thewe xDD is nyo way :3 a bee shouwd b
- [Dataset](https://www.kaggle.com/shivamb/35-million-tiktok-mobile-app-reviews) - [Dataset](https://www.kaggle.com/shivamb/35-million-tiktok-mobile-app-reviews)
- Size: `543.02 MiB` - Size: `543.02 MiB`
- TIme Taken: `38s` - TIme Taken: `4s`
![](examples/gifs/tiktok_app_reviews.gif) ![](examples/gifs/tiktok_app_reviews.gif)
@ -230,8 +220,8 @@ Accowding to aww knyown waws of aviation, thewe xDD is nyo way :3 a bee shouwd b
- [Dataset](https://www.kaggle.com/bittlingmayer/amazonreviews?select=train.ft.txt.bz2) - [Dataset](https://www.kaggle.com/bittlingmayer/amazonreviews?select=train.ft.txt.bz2)
- Size: `1.6 GiB` - Size: `1.6 GiB`
- Time Taken: `2:16m` - Time Taken: `21s`
- **DISCLAIMER:** The input is a 1.6GB file and the output is a 2GB file. They are not included in the repo. - **DISCLAIMER:** The input is a 1.6GB file and the output is a 2.2GB file. They are not included in the repo.
![](examples/gifs/amazon-ratings-reviews.gif) ![](examples/gifs/amazon-ratings-reviews.gif)

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:e7e4a7aef84ea7b6372a6f8843a34920859fe16d6bd0b1515cb42a050fbe8a8d oid sha256:fc99a3c03cc99b715f4bb7a598c3a15eb0bdf58e40a383b9ec5084c5186897a1
size 5075736 size 43789

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

@ -1,38 +1,38 @@
pub const FACES_SIZE: usize = 14; pub const FACES_SIZE: usize = 14;
pub const FACES: [&[u8]; FACES_SIZE] = [ pub const FACES: [&[u8]; FACES_SIZE] = [
b"OwO", b"OwO ",
b"UwU", b"UwU ",
b">w<", b">w< ",
b"^w^", b"^w^ ",
b"^-^", b"^-^ ",
b":3", b":3 ",
b"x3", b"x3 ",
b"xDD", b"xDD ",
b";;w;;", b";;w;; ",
b">_<", b">_< ",
b">_>", b">_> ",
b"^.^", b"^.^ ",
b":33", b":33 ",
b"uWu", b"uWu ",
]; ];
pub const ACTIONS_SIZE: usize = 17; pub const ACTIONS_SIZE: usize = 17;
pub const ACTIONS: [&[u8]; ACTIONS_SIZE] = [ pub const ACTIONS: [&[u8]; ACTIONS_SIZE] = [
b"*notices bulge*", b"*notices bulge* ",
b"*cries*", b"*cries* ",
b"*hugs tightly*", b"*hugs tightly* ",
b"*screams*", b"*screams* ",
b"*looks away*", b"*looks away* ",
b"*blushes*", b"*blushes* ",
b"*sweats*", b"*sweats* ",
b"*cuddles you*", b"*cuddles you* ",
b"*moans*", b"*moans* ",
b"*giggles shyly*", b"*giggles shyly* ",
b"*looks at you*", b"*looks at you* ",
b"*twerks*", b"*twerks* ",
b"*sighs*", b"*sighs* ",
b"*leans over*", b"*leans over* ",
b"*pokes you*", b"*pokes you* ",
b"*teleports behind you*", b"*teleports behind you* ",
b"*shuffles closer*", b"*shuffles closer* ",
]; ];

@ -1,25 +1,30 @@
use indicatif::{ProgressBar, ProgressStyle};
use linkify::{LinkFinder, LinkKind};
use rand::{Rng, RngCore, SeedableRng};
use rand_xoshiro::{Xoshiro256Plus, Xoshiro256PlusPlus};
use std::fs::File; use std::fs::File;
use std::io::{BufWriter, Error, Write}; use std::io::{stdout, BufWriter, Error, ErrorKind, Write};
use std::path::Path; use std::path::Path;
use std::str::from_utf8_unchecked;
use indicatif::{ProgressBar, ProgressStyle};
use linkify::{LinkFinder, LinkKind};
use memmap::Mmap;
use constants::ACTIONS; use constants::ACTIONS;
use constants::ACTIONS_SIZE; use constants::ACTIONS_SIZE;
use constants::FACES; use constants::FACES;
use constants::FACES_SIZE; use constants::FACES_SIZE;
use seeder::UwUSeeder;
mod constants; mod constants;
mod seeder;
macro_rules! progress_bar { macro_rules! progress_bar {
() => {{ ($bytes:expr) => {{
let progress_bar = ProgressBar::new_spinner(); let progress_bar = ProgressBar::new($bytes);
progress_bar.set_style( progress_bar.set_style(
ProgressStyle::default_spinner().template("{spinner:.green} [{elapsed_precise}] {msg}"), ProgressStyle::default_spinner()
.template("{spinner:.magenta} [{elapsed_precise:.bold}] {msg:.green.bold}"),
); );
progress_bar.enable_steady_tick(100); progress_bar.set_message("UwU'ifying In Progress...");
progress_bar.enable_steady_tick(30);
progress_bar progress_bar
}}; }};
@ -34,8 +39,8 @@ pub struct UwUify<'a> {
faces: f64, faces: f64,
actions: f64, actions: f64,
stutters: f64, stutters: f64,
floating_rng: Xoshiro256Plus, random: bool,
int_rng: Xoshiro256PlusPlus, is_runtime: bool,
linkify: LinkFinder, linkify: LinkFinder,
} }
@ -49,8 +54,8 @@ impl<'a> Default for UwUify<'a> {
faces: 0.05, faces: 0.05,
actions: 0.125, actions: 0.125,
stutters: 0.225, stutters: 0.225,
floating_rng: Xoshiro256Plus::seed_from_u64(69), random: false,
int_rng: Xoshiro256PlusPlus::seed_from_u64(420), is_runtime: false,
linkify: LinkFinder::new(), linkify: LinkFinder::new(),
} }
} }
@ -66,25 +71,22 @@ impl<'a> UwUify<'a> {
actions: Option<&'a str>, actions: Option<&'a str>,
stutters: Option<&'a str>, stutters: Option<&'a str>,
random: bool, random: bool,
is_runtime: bool,
) -> UwUify<'a> { ) -> UwUify<'a> {
// I dislike this
let mut linkify = LinkFinder::new(); let mut linkify = LinkFinder::new();
linkify.kinds(&[LinkKind::Email, LinkKind::Url]); linkify.kinds(&[LinkKind::Email, LinkKind::Url]);
linkify.url_must_have_scheme(false); linkify.url_must_have_scheme(false);
let mut uwuify = UwUify { let mut uwuify = UwUify {
text: text.unwrap_or_default(), text: text.unwrap_or_default(),
input: infile.unwrap_or_default(), input: infile.unwrap_or_default(),
output: outfile.unwrap_or_default(), output: outfile.unwrap_or_default(),
random,
is_runtime,
linkify, linkify,
..Default::default() ..Default::default()
}; };
if random {
uwuify.floating_rng = Xoshiro256Plus::seed_from_u64(rand::rngs::OsRng.next_u64());
uwuify.int_rng = Xoshiro256PlusPlus::seed_from_u64(rand::rngs::OsRng.next_u64());
}
if let Some(words) = words { if let Some(words) = words {
uwuify.words = words.parse::<f64>().unwrap(); uwuify.words = words.parse::<f64>().unwrap();
} }
@ -97,6 +99,7 @@ impl<'a> UwUify<'a> {
if let Some(stutters) = stutters { if let Some(stutters) = stutters {
uwuify.stutters = stutters.parse::<f64>().unwrap(); uwuify.stutters = stutters.parse::<f64>().unwrap();
} }
uwuify uwuify
} }
@ -107,85 +110,79 @@ impl<'a> UwUify<'a> {
if !self.output.is_empty() { if !self.output.is_empty() {
if Path::new(&self.output).exists() { if Path::new(&self.output).exists() {
return Err(Error::new( return Err(Error::new(
std::io::ErrorKind::AlreadyExists, ErrorKind::AlreadyExists,
format!("File '{}' already exists, aborting operation", &self.output), format!("File '{}' already exists, aborting operation", &self.output),
)); ));
} }
let mut uwu_out_file = BufWriter::new(File::create(&self.output)?); let uwu_progress_bar = progress_bar!(self.text.len() as u64);
let uwu_progress_bar = progress_bar!(); self.uwuify_sentence(self.text, &mut BufWriter::new(File::create(&self.output)?))?;
self.uwuify_sentence(self.text, &mut uwu_out_file)?;
uwu_progress_bar.finish_with_message("UwU'ifying Complete!"); uwu_progress_bar.finish_with_message("UwU'ifying Complete!");
Ok(())
} else { } else {
#[cfg(not(test))] self.uwuify_sentence(self.text, &mut BufWriter::new(stdout().lock()))?;
let stdout = std::io::stdout();
#[cfg(not(test))]
let mut out = BufWriter::new(stdout.lock());
#[cfg(test)]
let mut out = std::io::sink();
self.uwuify_sentence(self.text, &mut out)?;
#[cfg(not(test))]
out.write_all(b"\n")?;
Ok(())
} }
} else { } else {
// Handle File I/O // Handle File I/O
if Path::new(&self.output).exists() { if Path::new(&self.output).exists() {
return Err(Error::new( return Err(Error::new(
std::io::ErrorKind::AlreadyExists, ErrorKind::AlreadyExists,
format!("File '{}' already exists, aborting operation", &self.output), format!("File '{}' already exists, aborting operation", &self.output),
)); ));
} }
let uwu_progress_bar = progress_bar!(); let infile = File::open(&self.input)?;
let uwu_progress_bar = progress_bar!(infile.metadata()?.len());
self.uwuify_sentence( self.uwuify_sentence(
unsafe { unsafe { from_utf8_unchecked(Mmap::map(&infile)?.as_ref()) },
std::str::from_utf8_unchecked(
memmap::Mmap::map(&File::open(&self.input)?)?.as_ref(),
)
},
&mut BufWriter::new(File::create(&self.output)?), &mut BufWriter::new(File::create(&self.output)?),
)?; )?;
uwu_progress_bar.finish_with_message("UwU'ifying Complete!"); uwu_progress_bar.finish_with_message("UwU'ifying Complete!");
Ok(())
} }
Ok(())
} }
pub fn uwuify_sentence<T: Write>( pub fn uwuify_sentence<T: Write>(&mut self, text: &str, out: &mut T) -> Result<(), Error> {
&mut self,
text: &str,
out: &mut T,
) -> Result<(), std::io::Error> {
text.lines().try_for_each(|line| { text.lines().try_for_each(|line| {
line.split_whitespace() line.split_whitespace()
.map(|f| f.as_bytes()) .map(|word_str| word_str.as_bytes())
.try_for_each(|word| { .try_for_each(|word| {
let random_value = self.floating_rng.gen_range(0.0..1.0); let mut seeder = UwUSeeder::new(word, self.random);
let random_value = seeder.random_float();
if random_value <= self.faces {
out.write_all(FACES[self.int_rng.gen_range(0..FACES_SIZE)])?; if !self.is_runtime {
out.write_all(b" ")?; if random_value <= self.faces {
} else if random_value <= self.actions { out.write_all(FACES[seeder.random_int(0..FACES_SIZE)])?;
out.write_all(ACTIONS[self.int_rng.gen_range(0..ACTIONS_SIZE)])?; } else if random_value <= self.actions {
out.write_all(b" ")?; out.write_all(ACTIONS[seeder.random_int(0..ACTIONS_SIZE)])?;
} else if random_value <= self.stutters { } else if random_value <= self.stutters {
(0..self.int_rng.gen_range(1..2)) match word[0] {
.into_iter() b'L' | b'R' => out.write_all(b"W"),
.try_for_each(|_| { b'l' | b'r' => out.write_all(b"w"),
match word[0] { byte => out.write_all(&[byte]),
b'L' | b'R' => out.write_all(b"W"), }?;
b'l' | b'r' => out.write_all(b"w"), out.write_all(b"-")?;
b => out.write_all(&[b]), }
}?; } else {
out.write_all(b"-") if random_value <= self.faces {
})?; out.write_all(FACES[seeder.random_int(0..FACES_SIZE)])?;
}
if random_value <= self.actions {
out.write_all(ACTIONS[seeder.random_int(0..ACTIONS_SIZE)])?;
}
if random_value <= self.stutters {
match word[0] {
b'L' | b'R' => out.write_all(b"W"),
b'l' | b'r' => out.write_all(b"w"),
byte => out.write_all(&[byte]),
}?;
out.write_all(b"-")?;
}
} }
if self if self
.linkify .linkify
.links(unsafe { std::str::from_utf8_unchecked(word) }) .links(unsafe { from_utf8_unchecked(word) })
.count() .count()
> 0 > 0
|| random_value > self.words || random_value > self.words
@ -195,13 +192,13 @@ impl<'a> UwUify<'a> {
(0..word.len()).try_for_each(|index| match word[index] { (0..word.len()).try_for_each(|index| match word[index] {
b'L' | b'R' => out.write_all(b"W"), b'L' | b'R' => out.write_all(b"W"),
b'l' | b'r' => out.write_all(b"w"), b'l' | b'r' => out.write_all(b"w"),
b'E' | b'e' | b'A' | b'I' | b'O' | b'U' | b'a' | b'i' | b'o' | b'u' => { b'A' | b'E' | b'I' | b'O' | b'U' | b'a' | b'e' | b'i' | b'o' | b'u' => {
match word.get(index - 1).unwrap_or(&word[0]) { match word.get(index - 1).unwrap_or(&word[0]) {
b'N' | b'n' => out.write_all(&[b'y', word[index]]), b'N' | b'n' => out.write_all(&[b'y', word[index]]),
_ => out.write_all(&[word[index]]), _ => out.write_all(&[word[index]]),
} }
} }
b => out.write_all(&[b]), byte => out.write_all(&[byte]),
})?; })?;
} }
out.write_all(b" ") out.write_all(b" ")

@ -1,3 +1,5 @@
use std::panic::set_hook;
use clap::{Arg, ArgGroup, ErrorKind}; use clap::{Arg, ArgGroup, ErrorKind};
use uwuifyy::UwUify; use uwuifyy::UwUify;
@ -99,14 +101,17 @@ macro_rules! clap_panic {
}; };
} }
macro_rules! is_runtime {
($faces:expr, $actions:expr, $stutters:expr) => {
$faces > 0 || $actions > 0 || $stutters > 0
};
}
fn main() { fn main() {
std::panic::set_hook(Box::new(|info| { set_hook(Box::new(|info| clap_panic!(info)));
clap_panic!(info);
}));
let matches = app!().get_matches();
// panicing here ensures that the error is passed to the hook above instead of to stdout. let matches = app!().get_matches();
match UwUify::new( if let Err(err) = UwUify::new(
matches.value_of("text"), matches.value_of("text"),
matches.value_of("infile"), matches.value_of("infile"),
matches.value_of("outfile"), matches.value_of("outfile"),
@ -115,12 +120,16 @@ fn main() {
matches.value_of("actions"), matches.value_of("actions"),
matches.value_of("stutters"), matches.value_of("stutters"),
matches.is_present("random"), matches.is_present("random"),
is_runtime!(
matches.occurrences_of("faces"),
matches.occurrences_of("actions"),
matches.occurrences_of("stutters")
),
) )
.uwuify() .uwuify()
{ {
Err(e) => clap_panic!(e), clap_panic!(err);
_ => {} }
};
} }
fn is_between_zero_and_one(input: &str) -> Result<(), &'static str> { fn is_between_zero_and_one(input: &str) -> Result<(), &'static str> {

@ -0,0 +1,34 @@
use std::hash::Hasher;
use ahash::AHasher;
use rand::distributions::uniform::{SampleRange, SampleUniform};
use rand::{Rng, RngCore, SeedableRng};
use rand_xoshiro::Xoshiro256Plus;
pub struct UwUSeeder {
rng: Xoshiro256Plus,
}
impl UwUSeeder {
pub fn new(word: &[u8], random: bool) -> UwUSeeder {
let rand_u64 = if !random {
let mut hasher = AHasher::new_with_keys(0, 0);
hasher.write(word);
hasher.finish()
} else {
rand::rngs::OsRng::default().next_u64()
};
UwUSeeder {
rng: Xoshiro256Plus::seed_from_u64(rand_u64),
}
}
pub fn random_float(&mut self) -> f64 {
self.rng.gen_range(0.0..1.0)
}
pub fn random_int<T: SampleUniform, R: SampleRange<T>>(&mut self, range: R) -> T {
self.rng.gen_range(range)
}
}
Loading…
Cancel
Save