mirror of
https://github.com/nushell/nushell.git
synced 2025-01-03 04:50:28 +01:00
simple inc plugin implementation
This commit is contained in:
parent
e193bf43fb
commit
1d356276c2
43
Cargo.lock
generated
43
Cargo.lock
generated
@ -762,6 +762,16 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu_plugin_inc"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"nu-engine",
|
||||||
|
"nu-plugin",
|
||||||
|
"nu-protocol",
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
@ -861,6 +871,15 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||||
|
dependencies = [
|
||||||
|
"ucd-trie",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -1125,6 +1144,24 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
|
||||||
|
dependencies = [
|
||||||
|
"semver-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver-parser"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.130"
|
version = "1.0.130"
|
||||||
@ -1393,6 +1430,12 @@ version = "1.14.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
|
checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uncased"
|
name = "uncased"
|
||||||
version = "0.9.6"
|
version = "0.9.6"
|
||||||
|
@ -13,6 +13,7 @@ members = [
|
|||||||
"crates/nu-command",
|
"crates/nu-command",
|
||||||
"crates/nu-protocol",
|
"crates/nu-protocol",
|
||||||
"crates/nu-plugin",
|
"crates/nu-plugin",
|
||||||
|
"crates/nu_plugin_inc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -38,6 +38,7 @@ pub enum PluginError {
|
|||||||
UnableToSpawn(String),
|
UnableToSpawn(String),
|
||||||
EncodingError(String),
|
EncodingError(String),
|
||||||
DecodingError(String),
|
DecodingError(String),
|
||||||
|
RunTimeError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for PluginError {
|
impl Display for PluginError {
|
||||||
@ -54,6 +55,9 @@ impl Display for PluginError {
|
|||||||
PluginError::DecodingError(err) => {
|
PluginError::DecodingError(err) => {
|
||||||
write!(f, "error while decoding: {}", err)
|
write!(f, "error while decoding: {}", err)
|
||||||
}
|
}
|
||||||
|
PluginError::RunTimeError(err) => {
|
||||||
|
write!(f, "runtime error: {}", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,7 +228,7 @@ impl Command for PluginDeclaration {
|
|||||||
/// The `Plugin` trait defines the API which plugins use to "hook" into nushell.
|
/// The `Plugin` trait defines the API which plugins use to "hook" into nushell.
|
||||||
pub trait Plugin {
|
pub trait Plugin {
|
||||||
fn signature(&self) -> Vec<Signature>;
|
fn signature(&self) -> Vec<Signature>;
|
||||||
fn run(&self, name: &str, call: &Call, input: &Value) -> Result<Value, PluginError>;
|
fn run(&mut self, name: &str, call: &Call, input: &Value) -> Result<Value, PluginError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function used in the plugin definition for the communication protocol between
|
// Function used in the plugin definition for the communication protocol between
|
||||||
|
20
crates/nu_plugin_inc/cargo.toml
Normal file
20
crates/nu_plugin_inc/cargo.toml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
authors = ["The Nu Project Contributors"]
|
||||||
|
description = "A version incrementer plugin for Nushell"
|
||||||
|
edition = "2018"
|
||||||
|
license = "MIT"
|
||||||
|
name = "nu_plugin_inc"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nu-plugin = { path="../nu-plugin", version = "0.1.0" }
|
||||||
|
nu-protocol = { path="../nu-protocol", version = "0.1.0" }
|
||||||
|
nu-engine = { path="../nu-engine", version = "0.1.0" }
|
||||||
|
|
||||||
|
semver = "0.11.0"
|
||||||
|
|
||||||
|
|
||||||
|
[build-dependencies]
|
138
crates/nu_plugin_inc/src/inc.rs
Normal file
138
crates/nu_plugin_inc/src/inc.rs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
use nu_plugin::plugin::PluginError;
|
||||||
|
use nu_protocol::{Span, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
pub enum Action {
|
||||||
|
SemVerAction(SemVerAction),
|
||||||
|
Default,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
pub enum SemVerAction {
|
||||||
|
Major,
|
||||||
|
Minor,
|
||||||
|
Patch,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Inc {
|
||||||
|
pub error: Option<String>,
|
||||||
|
pub action: Option<Action>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Inc {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&self, input: &str) -> Value {
|
||||||
|
match &self.action {
|
||||||
|
Some(Action::SemVerAction(act_on)) => {
|
||||||
|
let mut ver = match semver::Version::parse(input) {
|
||||||
|
Ok(parsed_ver) => parsed_ver,
|
||||||
|
Err(_) => {
|
||||||
|
return Value::String {
|
||||||
|
val: input.to_string(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match act_on {
|
||||||
|
SemVerAction::Major => ver.increment_major(),
|
||||||
|
SemVerAction::Minor => ver.increment_minor(),
|
||||||
|
SemVerAction::Patch => ver.increment_patch(),
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::String {
|
||||||
|
val: ver.to_string(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(Action::Default) | None => match input.parse::<u64>() {
|
||||||
|
Ok(v) => Value::String {
|
||||||
|
val: (v + 1).to_string(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
Err(_) => Value::String {
|
||||||
|
val: input.to_string(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn for_semver(&mut self, part: SemVerAction) {
|
||||||
|
if self.permit() {
|
||||||
|
self.action = Some(Action::SemVerAction(part));
|
||||||
|
} else {
|
||||||
|
self.log_error("can only apply one");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn permit(&mut self) -> bool {
|
||||||
|
self.action.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log_error(&mut self, message: &str) {
|
||||||
|
self.error = Some(message.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn usage() -> &'static str {
|
||||||
|
"Usage: inc field [--major|--minor|--patch]"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inc(&self, value: &Value) -> Result<Value, PluginError> {
|
||||||
|
match value {
|
||||||
|
Value::Int { val, span } => Ok(Value::Int {
|
||||||
|
val: val + 1,
|
||||||
|
span: span.clone(),
|
||||||
|
}),
|
||||||
|
Value::String { val, .. } => Ok(self.apply(val)),
|
||||||
|
_ => Err(PluginError::RunTimeError("incrementable value".to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
mod semver {
|
||||||
|
use nu_protocol::{Span, Value};
|
||||||
|
|
||||||
|
use crate::inc::SemVerAction;
|
||||||
|
use crate::Inc;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn major() {
|
||||||
|
let expected = Value::String {
|
||||||
|
val: "1.0.0".to_string(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
};
|
||||||
|
let mut inc = Inc::new();
|
||||||
|
inc.for_semver(SemVerAction::Major);
|
||||||
|
assert_eq!(inc.apply("0.1.3"), expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn minor() {
|
||||||
|
let expected = Value::String {
|
||||||
|
val: "0.2.0".to_string(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
};
|
||||||
|
let mut inc = Inc::new();
|
||||||
|
inc.for_semver(SemVerAction::Minor);
|
||||||
|
assert_eq!(inc.apply("0.1.3"), expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn patch() {
|
||||||
|
let expected = Value::String {
|
||||||
|
val: "0.1.4".to_string(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
};
|
||||||
|
let mut inc = Inc::new();
|
||||||
|
inc.for_semver(SemVerAction::Patch);
|
||||||
|
assert_eq!(inc.apply("0.1.3"), expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
crates/nu_plugin_inc/src/lib.rs
Normal file
4
crates/nu_plugin_inc/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
mod inc;
|
||||||
|
mod nu;
|
||||||
|
|
||||||
|
pub use inc::Inc;
|
6
crates/nu_plugin_inc/src/main.rs
Normal file
6
crates/nu_plugin_inc/src/main.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use nu_plugin::serve_plugin;
|
||||||
|
use nu_plugin_inc::Inc;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
serve_plugin(&mut Inc::new())
|
||||||
|
}
|
47
crates/nu_plugin_inc/src/nu/mod.rs
Normal file
47
crates/nu_plugin_inc/src/nu/mod.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use crate::inc::SemVerAction;
|
||||||
|
use crate::Inc;
|
||||||
|
use nu_plugin::{plugin::PluginError, Plugin};
|
||||||
|
use nu_protocol::ast::Call;
|
||||||
|
use nu_protocol::{Signature, Span, Value};
|
||||||
|
|
||||||
|
impl Plugin for Inc {
|
||||||
|
fn signature(&self) -> Vec<Signature> {
|
||||||
|
vec![Signature::build("inc")
|
||||||
|
.desc("Increment a value or version. Optionally use the column of a table.")
|
||||||
|
.switch(
|
||||||
|
"major",
|
||||||
|
"increment the major version (eg 1.2.1 -> 2.0.0)",
|
||||||
|
Some('M'),
|
||||||
|
)
|
||||||
|
.switch(
|
||||||
|
"minor",
|
||||||
|
"increment the minor version (eg 1.2.1 -> 1.3.0)",
|
||||||
|
Some('m'),
|
||||||
|
)
|
||||||
|
.switch(
|
||||||
|
"patch",
|
||||||
|
"increment the patch version (eg 1.2.1 -> 1.2.2)",
|
||||||
|
Some('p'),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&mut self, name: &str, call: &Call, input: &Value) -> Result<Value, PluginError> {
|
||||||
|
if name != "inc" {
|
||||||
|
return Ok(Value::Nothing {
|
||||||
|
span: Span::unknown(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if call.has_flag("major") {
|
||||||
|
self.for_semver(SemVerAction::Major);
|
||||||
|
}
|
||||||
|
if call.has_flag("minor") {
|
||||||
|
self.for_semver(SemVerAction::Minor);
|
||||||
|
}
|
||||||
|
if call.has_flag("patch") {
|
||||||
|
self.for_semver(SemVerAction::Patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inc(input)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user