Improve docs and add filter's || to docs

This commit is contained in:
NGnius (Graham) 2022-01-16 21:48:32 -05:00
parent 64b8a7734d
commit 482d86aedc
5 changed files with 175 additions and 14 deletions

View file

@ -1,24 +1,32 @@
# mps # mps
An MPS program which plays music. A language all about interation to play your music files.
This project implements the interpreter (mps-interpreter), music player (mps-player), and CLI interface for MPS (root). This project implements the interpreter (mps-interpreter), music player (mps-player), and CLI interface for MPS (root).
The CLI interface includes a REPL for running scripts. The CLI interface includes a REPL for running scripts.
The REPL interactive mode also provides more details about using MPS through the `?help` command. The REPL interactive mode also provides more details about using MPS through the `?help` command.
### FAQ ## Usage
#### Is MPS Turing-Complete? To access the REPL, simply run `cargo run`. You will need the [Rust toolchain installed](https://rustup.rs/).
## Examples
For now, check out `./src/tests`, `./mps-player/tests`, and `./mps-interpreter/tests` for examples.
One day I'll add pretty REPL example pictures and some script files...
// TODO
## FAQ
### Is MPS Turing-Complete?
**No**. It can't perform arbitrary calculations (yet), which easily disqualifies MPS from being Turing-complete. **No**. It can't perform arbitrary calculations (yet), which easily disqualifies MPS from being Turing-complete.
#### Can I use MPS right now? ### Can I use MPS right now?
**Sure!** It's not complete, but MPS is completely useable for basic music queries right now. Hopefully most of the bugs have been ironed out as well... **Sure!** It's not complete, but MPS is completely useable for basic music queries right now. Hopefully most of the bugs have been ironed out as well...
#### Why write a new language? ### Why write a new language?
**I thought it would be fun**. I also wanted to be able to play my music without having to be at the whim of someone else's algorithm (and music), and playing just by album or artist was getting boring. I also thought designing a language specifically for iteration would be a novel approach to a language (though every approach is a novel approach for me). **I thought it would be fun**. I also wanted to be able to play my music without having to be at the whim of someone else's algorithm (and music), and playing just by album or artist was getting boring. I also thought designing a language specifically for iteration would be a novel approach to a language (though every approach is a novel approach for me).
#### What is MPS? ### What is MPS?
**Music Playlist Script (MPS) is technically a query language for music files.** It uses an (auto-generated) SQLite3 database for SQL queries and can also directly query the filesystem. Queries can be filtered and extended by using filters and functions built-in to MPS (see mps-interpreter's README.md). **Music Playlist Script (MPS) is technically a query language for music files.** It uses an (auto-generated) SQLite3 database for SQL queries and can also directly query the filesystem. Queries can be filtered and extended by using filters and functions built-in to MPS (see mps-interpreter's README.md).
#### Is MPS a scripting language? ### Is MPS a scripting language?
**No**. Technically, it was designed to be one, but it doesn't meet the requirements of a scripting language (yet). One day, I would like it be Turing-complete and then it could be considered a scripting language. At the moment it is barely a query language. **No**. Technically, it was designed to be one, but it doesn't meet the requirements of a scripting language (yet). One day, I would like it be Turing-complete and then it could be considered a scripting language. At the moment it is barely a query language.

View file

@ -29,5 +29,76 @@ for result in interpreter {
} }
``` ```
## Standard Vocabulary
By default, the standard vocabulary is used to parse the stream when iterating the interpreter.
The standard vocabulary defines the valid statement syntax for MPS and parses syntax into special Rust Iterators which can be used to execute the statement.
To declare your own vocabulary, use MpsRunner::with_settings to provide a MpsInterpretor with a custom vocabulary (I'm not sure why you would, but I'm not going to stop you).
### Oddities
The MPS standard syntax does a few things that most other languages don't, because I wanted it to.
\` can be used in place of " -- To make it easier to write SQL, string literals may be surrounded by backticks instead of quotation marks.
; -- The REPL will automatically place semicolons when Enter is pressed and it's not inside of brackets or a literal. MPS requires semicolons at the end of every statement, though, so MPS files must use semicolons.
### Filters
Operations to reduce the items in an iterable: `iterable.(filter);`.
Filters are statements of the format `something.(predicate)`, where "something" is a variable name or another valid statement, and "predicate" is a valid filter predicate (see below).
E.g. `files(folder="~/Music/", recursive=true).(title == "Romantic Traffic");` is valid filter syntax to filter all songs in the Music folder for songs named "Romantic Traffic" (probably just one song).
field == something
field != something
field >= something
field > something
field <= something
field < something -- e.g. iterable.(title == "Romantic Traffic");
Compare all items, keeping only those that match the condition. Valid field names are those of the MpsMusicItem (title, artist, album, genre, track, etc.), though this will change when proper object support is added. Optionally, a ? or ! can be added to the end of the field name to skip items whose field is missing/incomparable, or keep all items whose field is missing/incomparable (respectively).
start..end -- e.g. iterable.(0..42);
Keep only the items that are at the start index up to the end index. Start and/or end may be omitted to start/stop at the iterable's existing start/end (respectively). This stops once the end condition is met, leaving the rest of the iterator unconsumed.
start..=end -- e.g. iterable.(0..=42);
Keep only the items that are at the start index up to and including the end index. Start may be omitted to start at the iterable's existing start. This stops once the end condition is met, leaving the rest of the iterator unconsumed.
index -- e.g. iterable.(4);
Keep only the item at the given index. This stops once the index is reached, leaving the rest of the iterator unconsumed.
predicate1 || predicate2 -- e.g. iterable.(4 || 5);
Keep only the items that meet the criteria of predicate1 or predicate2. This will always consume the full iterator.
[empty] -- e.g. iterable.();
Matches all items
### Functions
Similar to most other languages: `function_name(param1, param2, etc.);`.
Functions are statements of the format `function_name(params)`, where "function_name" is one of the function names (below) and params is a valid parameter input for the function.
Each function is responsible for parsing it's own parameters when the statement is parsed, so this is very flexible.
E.g. `files(folder="~/Music/", recursive=true);` is valid function syntax to execute the files function with parameters `folder="~/Music/", recursive=true`.
sql_init(generate = true|false, folder = "path/to/music");
Initialize the SQLite database connection using the provided parameters. This must be performed before any other database operation (otherwise the database will already be connected with default settings).
sql("SQL query here");
Perform a raw SQLite query on the database which MPS auto-generates. An iterator of the results is returned.
song("something");
Retrieve all songs in the database with a title like something.
album("something");
Retrieve all songs in the database with an album title like something.
artist("something");
Retrieve all songs in the database with an artist name like something.
genre("something");
Retrieve all songs in the database with a genre title like something.
repeat(iterable, count);
Repeat the iterable count times, or infinite times if count is omitted.
files(folder = "path/to/music", recursive = true|false, regex = "pattern");
Retrieve all files from a folder, matching a regex pattern.
License: LGPL-2.1-only OR GPL-2.0-or-later License: LGPL-2.1-only OR GPL-2.0-or-later

View file

@ -27,6 +27,77 @@
//! } //! }
//! ``` //! ```
//! //!
//! # Standard Vocabulary
//! By default, the standard vocabulary is used to parse the stream when iterating the interpreter.
//! The standard vocabulary defines the valid statement syntax for MPS and parses syntax into special Rust Iterators which can be used to execute the statement.
//! To declare your own vocabulary, use MpsRunner::with_settings to provide a MpsInterpretor with a custom vocabulary (I'm not sure why you would, but I'm not going to stop you).
//!
//! ## Oddities
//! The MPS standard syntax does a few things that most other languages don't, because I wanted it to.
//!
//! \` can be used in place of " -- To make it easier to write SQL, string literals may be surrounded by backticks instead of quotation marks.
//!
//! ; -- The REPL will automatically place semicolons when Enter is pressed and it's not inside of brackets or a literal. MPS requires semicolons at the end of every statement, though, so MPS files must use semicolons.
//!
//! ## Filters
//! Operations to reduce the items in an iterable: `iterable.(filter);`.
//! Filters are statements of the format `something.(predicate)`, where "something" is a variable name or another valid statement, and "predicate" is a valid filter predicate (see below).
//! E.g. `files(folder="~/Music/", recursive=true).(title == "Romantic Traffic");` is valid filter syntax to filter all songs in the Music folder for songs named "Romantic Traffic" (probably just one song).
//!
//! field == something
//! field != something
//! field >= something
//! field > something
//! field <= something
//! field < something -- e.g. iterable.(title == "Romantic Traffic");
//! Compare all items, keeping only those that match the condition. Valid field names are those of the MpsMusicItem (title, artist, album, genre, track, etc.), though this will change when proper object support is added. Optionally, a ? or ! can be added to the end of the field name to skip items whose field is missing/incomparable, or keep all items whose field is missing/incomparable (respectively).
//!
//! start..end -- e.g. iterable.(0..42);
//! Keep only the items that are at the start index up to the end index. Start and/or end may be omitted to start/stop at the iterable's existing start/end (respectively). This stops once the end condition is met, leaving the rest of the iterator unconsumed.
//!
//! start..=end -- e.g. iterable.(0..=42);
//! Keep only the items that are at the start index up to and including the end index. Start may be omitted to start at the iterable's existing start. This stops once the end condition is met, leaving the rest of the iterator unconsumed.
//!
//! index -- e.g. iterable.(4);
//! Keep only the item at the given index. This stops once the index is reached, leaving the rest of the iterator unconsumed.
//!
//! predicate1 || predicate2 -- e.g. iterable.(4 || 5);
//! Keep only the items that meet the criteria of predicate1 or predicate2. This will always consume the full iterator.
//!
//! [empty] -- e.g. iterable.();
//! Matches all items
//!
//! ## Functions
//! Similar to most other languages: `function_name(param1, param2, etc.);`.
//! Functions are statements of the format `function_name(params)`, where "function_name" is one of the function names (below) and params is a valid parameter input for the function.
//! Each function is responsible for parsing it's own parameters when the statement is parsed, so this is very flexible.
//! E.g. `files(folder="~/Music/", recursive=true);` is valid function syntax to execute the files function with parameters `folder="~/Music/", recursive=true`.
//!
//!
//! sql_init(generate = true|false, folder = "path/to/music");
//! Initialize the SQLite database connection using the provided parameters. This must be performed before any other database operation (otherwise the database will already be connected with default settings).
//!
//! sql("SQL query here");
//! Perform a raw SQLite query on the database which MPS auto-generates. An iterator of the results is returned.
//!
//! song("something");
//! Retrieve all songs in the database with a title like something.
//!
//! album("something");
//! Retrieve all songs in the database with an album title like something.
//!
//! artist("something");
//! Retrieve all songs in the database with an artist name like something.
//!
//! genre("something");
//! Retrieve all songs in the database with a genre title like something.
//!
//! repeat(iterable, count);
//! Repeat the iterable count times, or infinite times if count is omitted.
//!
//! files(folder = "path/to/music", recursive = true|false, regex = "pattern");
//! Retrieve all files from a folder, matching a regex pattern.
//!
mod context; mod context;
mod interpretor; mod interpretor;

View file

@ -53,5 +53,8 @@ Operations to reduce the items in an iterable: iterable.(filter)
index -- e.g. iterable.(4) index -- e.g. iterable.(4)
Keep only the item at the given index. This stops once the index is reached, leaving the rest of the iterator unconsumed. Keep only the item at the given index. This stops once the index is reached, leaving the rest of the iterator unconsumed.
filter1 || filter2 -- e.g. iterable.(4 || 5)
Keep only the items that meet the criteria of filter1 or filter2. This will always consume the full iterator.
[empty] -- e.g. iterable.() [empty] -- e.g. iterable.()
Matches all items"; Matches all items";

View file

@ -1,22 +1,30 @@
//! An MPS program which plays music. //! A language all about interation to play your music files.
//! This project implements the interpreter (mps-interpreter), music player (mps-player), and CLI interface for MPS (root). //! This project implements the interpreter (mps-interpreter), music player (mps-player), and CLI interface for MPS (root).
//! The CLI interface includes a REPL for running scripts. //! The CLI interface includes a REPL for running scripts.
//! The REPL interactive mode also provides more details about using MPS through the `?help` command. //! The REPL interactive mode also provides more details about using MPS through the `?help` command.
//! //!
//! ## FAQ //! # Usage
//! ### Is MPS Turing-Complete? //! To access the REPL, simply run `cargo run`. You will need the [Rust toolchain installed](https://rustup.rs/).
//!
//! # Examples
//! For now, check out `./src/tests`, `./mps-player/tests`, and `./mps-interpreter/tests` for examples.
//! One day I'll add pretty REPL example pictures and some script files...
//! // TODO
//!
//! # FAQ
//! ## Is MPS Turing-Complete?
//! **No**. It can't perform arbitrary calculations (yet), which easily disqualifies MPS from being Turing-complete. //! **No**. It can't perform arbitrary calculations (yet), which easily disqualifies MPS from being Turing-complete.
//! //!
//! ### Can I use MPS right now? //! ## Can I use MPS right now?
//! **Sure!** It's not complete, but MPS is completely useable for basic music queries right now. Hopefully most of the bugs have been ironed out as well... //! **Sure!** It's not complete, but MPS is completely useable for basic music queries right now. Hopefully most of the bugs have been ironed out as well...
//! //!
//! ### Why write a new language? //! ## Why write a new language?
//! **I thought it would be fun**. I also wanted to be able to play my music without having to be at the whim of someone else's algorithm (and music), and playing just by album or artist was getting boring. I also thought designing a language specifically for iteration would be a novel approach to a language (though every approach is a novel approach for me). //! **I thought it would be fun**. I also wanted to be able to play my music without having to be at the whim of someone else's algorithm (and music), and playing just by album or artist was getting boring. I also thought designing a language specifically for iteration would be a novel approach to a language (though every approach is a novel approach for me).
//! //!
//! ### What is MPS? //! ## What is MPS?
//! **Music Playlist Script (MPS) is technically a query language for music files.** It uses an (auto-generated) SQLite3 database for SQL queries and can also directly query the filesystem. Queries can be filtered and extended by using filters and functions built-in to MPS (see mps-interpreter's README.md). //! **Music Playlist Script (MPS) is technically a query language for music files.** It uses an (auto-generated) SQLite3 database for SQL queries and can also directly query the filesystem. Queries can be filtered and extended by using filters and functions built-in to MPS (see mps-interpreter's README.md).
//! //!
//! ### Is MPS a scripting language? //! ## Is MPS a scripting language?
//! **No**. Technically, it was designed to be one, but it doesn't meet the requirements of a scripting language (yet). One day, I would like it be Turing-complete and then it could be considered a scripting language. At the moment it is barely a query language. //! **No**. Technically, it was designed to be one, but it doesn't meet the requirements of a scripting language (yet). One day, I would like it be Turing-complete and then it could be considered a scripting language. At the moment it is barely a query language.
//! //!