Implement simple CLI for executing scripts
This commit is contained in:
parent
0ad2c33ecb
commit
7d15f27465
7 changed files with 213 additions and 20 deletions
132
Cargo.lock
generated
132
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
16
src/cli.rs
Normal 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()
|
||||
}
|
74
src/main.rs
74
src/main.rs
|
@ -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
2
tests/test.mps
Normal 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'`);
|
Loading…
Reference in a new issue