Implement simple CLI for executing scripts

This commit is contained in:
NGnius (Graham) 2022-01-02 20:20:09 -05:00
parent 0ad2c33ecb
commit 7d15f27465
7 changed files with 213 additions and 20 deletions

132
Cargo.lock generated
View file

@ -50,6 +50,17 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
@ -146,6 +157,36 @@ dependencies = [
"libloading",
]
[[package]]
name = "clap"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d17bf219fcd37199b9a29e00ba65dfb8cd5b2688b7297ec14ff829c40ac50ca9"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"indexmap",
"lazy_static",
"os_str_bytes",
"strsim 0.10.0",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1b9752c030a14235a0bd5ef3ad60a1dcac8468c30921327fc8af36b20c790b9"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "claxon"
version = "0.4.3"
@ -232,7 +273,7 @@ dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"strsim 0.9.3",
"syn",
]
@ -371,6 +412,24 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hound"
version = "3.4.0"
@ -383,6 +442,16 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -567,6 +636,7 @@ dependencies = [
name = "mps"
version = "0.1.0"
dependencies = [
"clap",
"mps-interpreter",
"mps-player",
]
@ -777,6 +847,15 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "os_str_bytes"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
dependencies = [
"memchr",
]
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -833,6 +912,30 @@ dependencies = [
"toml",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.32"
@ -986,6 +1089,12 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "symphonia"
version = "0.4.0"
@ -1143,6 +1252,21 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
[[package]]
name = "thiserror"
version = "1.0.30"
@ -1187,6 +1311,12 @@ dependencies = [
"serde",
]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-xid"
version = "0.2.2"

View file

@ -5,7 +5,6 @@ edition = "2021"
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
description = "Music Playlist Scripting language (MPS)"
license = "LGPL-2.1-only OR GPL-2.0-or-later"
license-file = "LICENSE"
readme = "README.md"
[workspace]
@ -16,5 +15,7 @@ members = [
[dependencies]
# local
mps-interpreter = { path = "./mps-interpreter" }
mps-player = { path = "./mps-player" }
mps-interpreter = { version = "0.1.0", path = "./mps-interpreter" }
mps-player = { version = "0.1.0", path = "./mps-player" }
# external
clap = { version = "3.0", features = ["derive"] }

View file

@ -3,7 +3,6 @@ name = "mps-interpreter"
version = "0.1.0"
edition = "2021"
license = "LGPL-2.1-only OR GPL-2.0-or-later"
license-file = "LICENSE"
readme = "README.md"
[dependencies]

View file

@ -3,7 +3,6 @@ name = "mps-player"
version = "0.1.0"
edition = "2021"
license = "LGPL-2.1-only OR GPL-2.0-or-later"
license-file = "LICENSE"
readme = "README.md"
[dependencies]

16
src/cli.rs Normal file
View file

@ -0,0 +1,16 @@
use clap::{Parser};
#[derive(Parser)]
#[clap(author, version)]
#[clap(about = "Music playlist scripting language runtime")]
pub struct CliArgs {
/// Script to run
pub file: Option<String>,
/// Generate m3u8 playlist
#[clap(short, long)]
pub playlist: Option<String>,
}
pub fn parse() -> CliArgs {
CliArgs::parse()
}

View file

@ -3,7 +3,12 @@
//!
//! Future home of a MPS REPL for playing music ergonomically through a CLI.
//!
mod cli;
use std::io;
use std::path::PathBuf;
use mps_interpreter::MpsRunner;
use mps_player::{MpsPlayer, PlaybackError, MpsController};
@ -16,19 +21,60 @@ fn play_cursor() -> Result<(), PlaybackError> {
}
fn main() {
//play_cursor().unwrap();
let ctrl = MpsController::create(|| {
//let cursor = io::Cursor::<&'static str>::new("sql(`SELECT * FROM songs JOIN artists ON songs.artist = artists.artist_id WHERE artists.name like 'thundercat'`);");
let cursor = io::Cursor::<&'static str>::new(
"sql(`SELECT * FROM songs JOIN artists ON songs.artist = artists.artist_id WHERE artists.name like 'thundercat'`);
artist(`gwen`);"
);
let runner = MpsRunner::with_stream(cursor);
let player = MpsPlayer::new(runner).unwrap();
player.set_volume(0.8);
player
});
let args = cli::parse();
ctrl.wait_for_done().unwrap();
//ctrl.exit().unwrap(); // don't use both
if let Some(script_file) = &args.file {
// interpret script
// script file checks
if let Err(_) = file_checks(script_file) {
return;
}
// build playback controller
let script_file2 = script_file.clone();
let player_builder = move || {
let script_reader = io::BufReader::new(
std::fs::File::open(&script_file2)
.expect(&format!("Abort: Cannot open file `{}`", &script_file2))
);
let runner = MpsRunner::with_stream(script_reader);
let player = MpsPlayer::new(runner).unwrap();
player
};
if let Some(playlist_file) = &args.playlist {
// generate playlist
let mut player = player_builder();
let mut writer = io::BufWriter::new(
std::fs::File::create(playlist_file)
.expect(&format!("Abort: Cannot create writeable file `{}`", playlist_file))
);
match player.save_m3u8(&mut writer) {
Ok(_) => println!("Succes: Finished playlist `{}` from script `{}`", playlist_file, script_file),
Err(e) => eprintln!("{}", e),
}
} else {
// live playback
let ctrl = MpsController::create(player_builder);
match ctrl.wait_for_done() {
Ok(_) => println!("Succes: Finished playback from script `{}`", script_file),
Err(e) => eprintln!("{}", e),
}
}
} else {
// start REPL
// TODO
eprintln!("Abort: Cannot start REPL because it is not implemented yet :(");
}
}
fn file_checks(path_str: &str) -> Result<(), ()> {
let path = PathBuf::from(path_str);
if !path.exists() {
eprintln!("Abort: File `{}` does not exist", path_str);
return Err(());
}
if !path.is_file() {
eprintln!("Abort: Path `{}` is not a file", path_str);
return Err(());
}
Ok(())
}

2
tests/test.mps Normal file
View file

@ -0,0 +1,2 @@
sql_init(generate = false);
sql(`SELECT * FROM songs JOIN artists ON songs.artist = artists.artist_id WHERE artists.name like 'thundercat'`);