Improved seek command to allow more units (#682)

* `seek` command accepts fancy duration

* Use default formatting

* Better var naming

* Documented `seek` command
This commit is contained in:
cyqsimon
2021-12-27 16:28:49 +08:00
committed by GitHub
parent 0947a074d9
commit e0ec759730
4 changed files with 101 additions and 26 deletions

67
Cargo.lock generated
View File

@@ -611,7 +611,7 @@ dependencies = [
"lazy_static 1.4.0",
"libc",
"log",
"num",
"num 0.3.1",
"owning_ref",
"syn",
"unicode-segmentation",
@@ -1470,7 +1470,7 @@ dependencies = [
"hyper-proxy",
"librespot-protocol",
"log",
"num-bigint",
"num-bigint 0.4.3",
"num-integer",
"num-traits",
"once_cell",
@@ -1738,6 +1738,7 @@ dependencies = [
"log",
"notify-rust",
"pancurses 0.17.0",
"parse_duration",
"platform-dirs",
"rand",
"regex",
@@ -1919,16 +1920,41 @@ dependencies = [
"winapi",
]
[[package]]
name = "num"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
dependencies = [
"num-bigint 0.2.6",
"num-complex 0.2.4",
"num-integer",
"num-iter",
"num-rational 0.2.4",
"num-traits",
]
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-complex",
"num-complex 0.3.1",
"num-integer",
"num-iter",
"num-rational",
"num-rational 0.3.2",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
@@ -1944,6 +1970,16 @@ dependencies = [
"rand",
]
[[package]]
name = "num-complex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.3.1"
@@ -1985,6 +2021,18 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
"autocfg",
"num-bigint 0.2.6",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
@@ -2259,6 +2307,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "parse_duration"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7037e5e93e0172a5a96874380bf73bc6ecef022e26fa25f2be26864d6b3ba95d"
dependencies = [
"lazy_static 1.4.0",
"num 0.2.1",
"regex",
]
[[package]]
name = "pbkdf2"
version = "0.8.0"

View File

@@ -47,6 +47,7 @@ ioctl-rs = { version = "0.2", optional = true }
serde_cbor = "0.11.2"
pancurses = { version = "0.17.0", features = ["win32"], optional = true }
libc = "0.2.111"
parse_duration = "2.1.1"
[dependencies.rspotify]
version = "0.11.3"

View File

@@ -265,6 +265,7 @@ The following commands are supported:
| `logout` | Remove any cached credentials from disk and quit `ncspot`. |
| `toggle` | Toggle playback. |
| `stop` | Stop playback. |
| `seek [+\|-]<time>` | Seek to the specified position, or seek relative to current position by prepending `+`/`-`. Supports mixing time units (e.g. `seek 1m42s`). Default unit is `millisecond`. |
| `previous` | Play previous track. |
| `next` | Play next track. |
| `clear` | Clear playlist. |

View File

@@ -377,29 +377,43 @@ pub fn parse(input: &str) -> Option<Vec<Command>> {
Some(Command::Repeat(mode))
}
"seek" => args.get(0).and_then(|arg| match arg.chars().next() {
Some(x) if x == '-' || x == '+' => arg
.chars()
.skip(1)
.collect::<String>()
.parse::<i32>()
"seek" => {
let arg = args.join(" ");
let first_char = arg.chars().next();
let duration_raw = match first_char {
Some('+' | '-') => arg.chars().skip(1).collect(),
_ => arg.to_string(),
};
duration_raw
.parse::<u32>() // accept raw milliseconds for backward compatibility
.ok()
.map(|amount| {
Command::Seek(SeekDirection::Relative(
amount
* match x {
'-' => -1,
_ => 1,
},
))
}),
_ => arg
.chars()
.collect::<String>()
.parse()
.ok()
.map(|amount| Command::Seek(SeekDirection::Absolute(amount))),
}),
.or_else(|| {
parse_duration::parse(&duration_raw) // accept fancy duration
.ok()
.and_then(|dur| dur.as_millis().try_into().ok())
})
.and_then(|unsigned_millis| {
match first_char {
// handle i32::MAX < unsigned_millis < u32::MAX gracefully
Some('+') => {
i32::try_from(unsigned_millis)
.ok()
.map(|unsigned_millis_i32| {
SeekDirection::Relative(unsigned_millis_i32)
})
}
Some('-') => {
i32::try_from(unsigned_millis)
.ok()
.map(|unsigned_millis_i32| {
SeekDirection::Relative(-unsigned_millis_i32)
})
}
_ => Some(SeekDirection::Absolute(unsigned_millis)),
}
.map(|direction| Command::Seek(direction))
})
}
"focus" => args
.get(0)
.map(|target| Command::Focus((*target).to_string())),