mirror of
https://github.com/nushell/nushell.git
synced 2025-08-12 00:50:13 +02:00
nu-cmd-extra crate infrastructure in place with the Bits command as the model for adding other commands (#9327)
I wanted to get the infrastructure in place for starters for our *nu-cmd-extra* crate... The plan is to put inside here the following commands... * bits * bytes * math I thought it would be easier to do one at a time as well as get the nu-cmd-extra crate out there on crates.io for this upcoming release... Once this lands the infrastructure will be in place to move over the other noted commands for now... And then add other stuff we do NOT want to be in 1.0.
This commit is contained in:
104
crates/nu-cmd-extra/src/extra/bits/and.rs
Normal file
104
crates/nu-cmd-extra/src/extra/bits/and.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
impl Command for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"bits and"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits and")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required(
|
||||
"target",
|
||||
SyntaxShape::Int,
|
||||
"target integer to perform bit and",
|
||||
)
|
||||
.category(Category::Bits)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Performs bitwise and for integers."
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
vec!["logic and"]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let target: i64 = call.req(engine_state, stack, 0)?;
|
||||
|
||||
// This doesn't match explicit nulls
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
input.map(
|
||||
move |value| operate(value, target, head),
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Apply bits and to two numbers",
|
||||
example: "2 | bits and 2",
|
||||
result: Some(Value::test_int(2)),
|
||||
},
|
||||
Example {
|
||||
description: "Apply logical and to a list of numbers",
|
||||
example: "[4 3 2] | bits and 2",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_int(0), Value::test_int(2), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(value: Value, target: i64, head: Span) -> Value {
|
||||
match value {
|
||||
Value::Int { val, span } => Value::Int {
|
||||
val: val & target,
|
||||
span,
|
||||
},
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user