Crates.io | snakepipe |
lib.rs | snakepipe |
version | 2.2.0 |
source | src |
created_at | 2024-02-12 17:33:06.909995 |
updated_at | 2024-05-29 21:11:43.949247 |
description | A snake game based on stdin/stdout following unix philosophy |
homepage | |
repository | https://github.com/topheman/snake-pipe-rust |
max_upload_size | |
id | 1137197 |
size | 251,855 |
Not just yet another snake game in the terminal 😉.
https://github.com/topheman/snake-pipe-rust/assets/985982/76161595-1c3a-4252-9cbd-25e144bf185c
This one follows the unix philosophy as:
snakepipe gamestate
accepts user inputs, calculates the state of the game and writes it to stdout
snakepipe render
reads the state of the game from stdin
and renders it on the terminalsnakepipe throttle
reads a pre-recorded game from stdin
and writes to stdout
each tick so that snakepipe render
can pick it upsnakepipe render-browser
spawns a server and sends stdin
via server-sent events to a JavaScript renderer in your browsersnakepipe stream-sse
connects to the server spawned by render-browser
and streams server-sent events back to the terminalsnakepipe socket-play
accepts gamestate from stdin and pushes it to a unix socketsnakepipe socket-watch
reads gamestate from a unix socketsnakepipe tcp-play
accepts gamestate from stdin and pushes it to a tcp socketsnakepipe tcp-watch
reads gamestate from a tcp socketsnakepipe pipeline <command>
prints out the most common pipelines (combinations of commands), so that you could directly pbcopy
/paste themThat way:
gamestate
or render
command in any programming language and make it work with mineI've already done a few rust projects (with WebAssembly or bevy), however, I wanted something that needs to deal directly with:
Any OS - if you have Rust >= 1.75.0 - How to install Rust (if you don't have it yet)
cargo install snakepipe
On MacOS, with Homebrew (ships with its own shell completions for zsh, bash and fish)
brew install topheman/tap/snakepipe
Other OS: see releases.
# basic usage
snakepipe gamestate|snakepipe render
# change the defaults
snakepipe gamestate --frame-duration 80 --width 70 --height 20 --snakepipe-length 15|snakepipe render
# call help on any of the commands
snakepipe --help
# record a game into a file using the builtin `tee` command utility
snakepipe gamestate|tee /tmp/snakepipe-output|snakepipe render
# replay the game you recorded
cat /tmp/snakepipe-output|snakepipe throttle|snakepipe render
snakepipe gamestate|snakepipe render-browser|snakepipe render
Then open http://localhost:8080. You'll be able to switch between renderers in your browser as you are playing in your terminal (thanks to server-sent events).
Open two terminals:
# main terminal:
# - accepts user inputs
# - spawns an http server that streams stdin to server-sent events
# - renders the game to the terminal so you can play
snakepipe gamestate|snakepipe render-browser|snakepipe render
# mirroring terminal (not necessary the same device, only need to be on the same network):
# - connects to the http server and streams server-sent events to sdout
# - render the gamestate retrieved from the server
snakepipe stream-sse|snakepipe render
You could share your game accross your LAN!
Open two terminals. snakepipe tcp-play
will expose a process that accepts tcp connections (on port 8050 by default). You can connect to it via netcat (the nc
command), that will pipe the tcp stream output to stdout.
# main terminal
snakepipe gamestate|snakepipe tcp-play|snakepipe render
# mirroring terminal
nc localhost 8050|snakepipe render # with netcat
snakepipe tcp-watch|snakepipe render # or with snakepipe itself
Open two terminals. snakepipe socket-play
will expose a unix domain socket (by default on /tmp/snakepipe.sock
). You can connect to it via netcat (the nc
command), that will pipe the socket stream to stdout.
# main terminal
snakepipe gamestate|snakepipe socket-play|snakepipe render
# mirroring terminal
nc -U /tmp/snakepipe.sock|snakepipe render # with netcat
snakepipe socket-watch|snakepipe render # or with snakepipe itself
You should prefer using IPC.
Open two terminals that will communicate via a file that will be tail
ed and piped to snakepipe render
# mirroring terminal
cat /dev/null > /tmp/snakepipe-output && tail -f /tmp/snakepipe-output|snakepipe render
# main terminal
snakepipe gamestate|tee /tmp/snakepipe-output|snakepipe render
If you install snakepipe
with Homebrew, it ships with its own completions for zsh, bash and fish and they will be installed without you having to do anything.
If you installed snakepipe
manually, you can generate the completions files with the snakepipe generate-completions
command.
snakepipe --help
A snake game based on stdin/stdout following unix philosophyUsage: snakepipe <COMMAND>
Commands:
gamestate Accepts user inputs (arrow keys to control the snake) and outputs the state of the game to stdout render Reads gamestate from stdin and renders the game on your terminal throttle Reads stdin line by line and outputs each line on stdout each
frame_duration
ms (usefull for replaying a file) render-browser Let's you render the game in your browser at http://localhost:8080 by spawning a server and sending stdin via server-sent events to a JavaScript renderer stream-sse Connects to the server spawned byrender-browser
and streams server-sent events back to the terminal help Print this message or the help of the given subcommand(s)Options: -h, --help Print help -V, --version Print version
snakepipe gamestate --help
Accepts user inputs (arrow keys to control the snake) and outputs the state of the game to stdoutUsage: snakepipe gamestate [OPTIONS]
Options: --frame-duration <FRAME_DURATION> in ms [default: 120] --width <WIDTH> default 25 --height <HEIGHT> default 25 --snake-length <SNAKE_LENGTH> [default: 2] --fit-terminal
snakepipe render --help
Reads gamestate from stdin and renders the game on your terminalUsage: snakepipe render
snakepipe throttle --help
Reads stdin line by line and outputs each line on stdout each `frame_duration` ms (usefull for replaying a file)Usage: snakepipe throttle [OPTIONS]
Options: --frame-duration <FRAME_DURATION> in ms [default: 120] --loop-infinite
snakepipe render-browser --help
Let's you render the game in your browser at http://localhost:8080 by spawning a server and sending stdin via server-sent events to a JavaScript rendererUsage: snakepipe render-browser [OPTIONS]
Options: --port
[default: 8080]
snakepipe stream-sse --help
Connects to the server spawned by `render-browser` and streams server-sent events back to the terminalUsage: snakepipe stream-sse [OPTIONS]
Options: --address <ADDRESS> [default: http://localhost:8080]
snakepipe socket-play --help
Accepts gamestate from stdin and pushes it to a unix socketUsage: snakepipe socket-play [OPTIONS]
Options: --path <PATH> Unix socket file path [default: /tmp/snakepipe.sock]
snakepipe socket-watch --help
Reads gamestate from a unix socketUsage: snakepipe socket-watch [OPTIONS]
Options: --path <PATH> Unix socket file path [default: /tmp/snakepipe.sock]
snakepipe tcp-play --help
Accepts gamestate from stdin and pushes it to a tcp socketUsage: snakepipe tcp-play [OPTIONS]
Options: --port <PORT> Port number [default: 8050] --host <HOST> Tcp host [default: 127.0.0.1]
snakepipe tcp-watch --help
Reads gamestate from a tcp socketUsage: snakepipe tcp-watch [OPTIONS]
Options: --port <PORT> Port number [default: 8050] --host <HOST> Tcp host [default: 127.0.0.1]
snakepipe pipeline --help
Prints out some common pipelines, so that you can copy/paste them to execute (you can pipe to `pbcopy`)Usage: snakepipe pipeline [OPTIONS] [COMMAND]
Commands: play Play in the terminal record Record a party in the terminal replay Replay a party you recorded in the terminal file-play Play and share a party via a shared file in realtime file-watch Render the party you are sharing through a file in realtime http-play Play and share a party through an http server http-watch Render the party you shared through the http server, in the terminal
cargo add snakepipe # add it to your project
This crate is a cli, but it also exports a lib from where you can import a few utilities, such as snakepipe::stream::parse_gamestate
- direct link to docs.rs:
use snakepipe::stream::{parse_gamestate, Game};
fn main() -> () {
match parse_gamestate() {
Ok(stream) => {
println!(
"Frame duration {}, Snake length {}, Level {}x{}",
stream.options.frame_duration,
stream.options.snake_length,
stream.options.size.width,
stream.options.size.height
);
for parsed_line in stream.lines {
do_something(parsed_line);
}
}
Err(e) => {
eprintln!("Error occurred while parsing stdin: \"{}\"", e);
}
}
}
fn do_something(parsed_line: Game) {
println!("Snake head position {:?}", parsed_line.snake.head)
}
You can:
snakepipe render
command for the terminal in an other language than rustsnakepipe render-browser
command and ask for a PR to integrate it to the projectAn Experimental/Partial nodejs implementation of this crate available at topheman/snake-pipe-node.
More infos in CONTRIBUTING.md.