Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ permissions:
contents: read

env:
clippy_rust_version: '1.84'
clippy_rust_version: '1.88'

jobs:
test:
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ readme = "README.md"
license = "MIT"
repository = "https://github.com/synek317/shellfn"
documentation = "https://docs.rs/shellfn"
edition = "2018"
edition = "2024"

[workspace]
members = ["shellfn-attribute", "shellfn-core"]
Expand Down
2 changes: 1 addition & 1 deletion examples/calendar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ fn run(module: &str) -> Result<String, Box<dyn Error>> {
}

fn main() -> Result<(), Box<dyn Error>> {
run("calendar").map(|output| println!("{}", output))
run("calendar").map(|output| println!("{output}"))
}
4 changes: 2 additions & 2 deletions examples/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use shellfn::shell;
use std::error::Error;

#[shell]
fn list_modified(dir: &str) -> Result<impl Iterator<Item = String>, Box<dyn Error>> {
fn list_modified(dir: &str) -> Result<impl Iterator<Item = String> + use<>, Box<dyn Error>> {
r#"
cd $DIR
git status | grep '^\s*modified:' | awk '{print $2}'
Expand All @@ -11,7 +11,7 @@ fn list_modified(dir: &str) -> Result<impl Iterator<Item = String>, Box<dyn Erro

fn main() -> Result<(), Box<dyn Error>> {
for modified in list_modified(".")? {
println!("You have modified the file: {}", modified);
println!("You have modified the file: {modified}");
}
Ok(())
}
2 changes: 1 addition & 1 deletion examples/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ print(json.dumps(obj, indent=indent, sort_keys=sort_keys))
fn main() -> Result<(), Box<dyn Error>> {
let json = r#"{"foo": 42, "bar": { "baz": 10, "qux": [1, 2, 3]}}"#;
let pretty_json = pretty_json(json, 2, false)?;
println!("{}", pretty_json);
println!("{pretty_json}");
Ok(())
}
1 change: 0 additions & 1 deletion rustfmt.toml

This file was deleted.

6 changes: 3 additions & 3 deletions shellfn-attribute/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ version = "0.2.0"
authors = ["Marcin Sas-Szymanski <marcin.sas-szymanski@anixe.pl>"]
description = "Attribute macro for `shellfn` crate"
license = "MIT"
edition = "2018"
edition = "2024"

[lib]
doctest = false
proc-macro = true
path = "src/lib.rs"

[dependencies]
syn = { version = "2", features = ["full", "extra-traits"] }
syn = { version = "3", features = ["full", "extra-traits"] }
quote = "1"
proc-macro2 = "1"
darling = "0.20"
darling = "0.24"
shellwords = "1"
shellfn-core = { path = "../shellfn-core", version = "0.2.0" }
2 changes: 1 addition & 1 deletion shellfn-attribute/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use darling::FromMeta;
#[derive(Debug, Default, FromMeta)]
pub struct Attributes {
#[darling(default = "default_cmd")]
pub cmd: String,
pub cmd: String,
#[darling(default)]
pub no_panic: bool,
}
Expand Down
50 changes: 24 additions & 26 deletions shellfn-attribute/src/block_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ const PROGRAM: &str = "PROGRAM";

#[derive(Default)]
pub struct BlockBuilder {
program: String,
cmd: String,
args: Vec<String>,
envs: Vec<String>,
output_type: OutputType,
program: String,
cmd: String,
args: Vec<String>,
envs: Vec<String>,
output_type: OutputType,
outer_result: bool,
inner_result: bool,
no_panic: bool,
no_panic: bool,
}

impl BlockBuilder {
Expand Down Expand Up @@ -48,15 +48,15 @@ impl BlockBuilder {
}

pub fn with_args<'a>(mut self, args: impl Iterator<Item = &'a FnArg>) -> Self {
use syn::Pat::*;
use FnArg::*;
use syn::Pat::*;

for arg in args {
self.envs.push(
match arg {
Receiver(_) => "self".to_string(),
Typed(pat_type) => match pat_type.pat.as_ref() {
Ident(ref pat_ident) => pat_ident.ident.to_string(),
Ident(pat_ident) => pat_ident.ident.to_string(),
Wild(_) => continue,
_ => panic!("captured arguments with pattern other than simple Ident are not yet supported"),
},
Expand All @@ -71,37 +71,37 @@ impl BlockBuilder {
ReturnType::Default => {
self.with_unit_return_type();
}
ReturnType::Type(_, ref t) => match **t {
Type::Path(ref type_path) if is_result_type_path(type_path) => {
ReturnType::Type(_, t) => match *t {
Type::Path(type_path) if is_result_type_path(&type_path) => {
self.outer_result = true;

let args = &type_path.path.segments.last().unwrap().arguments;

if let PathArguments::AngleBracketed(path_args) = args {
if let Some(arg) = path_args.args.first() {
match arg {
GenericArgument::Type(Type::ImplTrait(ref imp)) => {
GenericArgument::Type(Type::ImplTrait(imp)) => {
self.with_impl_trait(imp)
}
GenericArgument::Type(ref t) if is_unit_type(t) => {
GenericArgument::Type(t) if is_unit_type(t) => {
self.with_unit_return_type();
}
GenericArgument::Type(ref t) if is_vec_type(t) => {
GenericArgument::Type(t) if is_vec_type(t) => {
self.with_vec_return_type(t);
}
_ => {}
}
}
}
}
Type::ImplTrait(ref imp) => {
Type::ImplTrait(imp) => {
self.outer_result = false;
self.with_impl_trait(imp);
self.with_impl_trait(&imp);
}
ref t if is_vec_type(t) => self.with_vec_return_type(t),
ref t if is_unit_type(t) => self.with_unit_return_type(),
t if is_vec_type(&t) => self.with_vec_return_type(&t),
t if is_unit_type(&t) => self.with_unit_return_type(),
Type::Path(_) => {}
ref t => panic!("Unsupported return type {:#?}", t),
t => panic!("Unsupported return type {t:#?}"),
},
}
self
Expand All @@ -114,27 +114,25 @@ impl BlockBuilder {
fn with_vec_return_type(&mut self, typ: &Type) {
self.output_type = OutputType::Vec;

if let Type::Path(ref type_path) = typ {
if let Type::Path(type_path) = typ {
let args = &type_path.path.segments.last().unwrap().arguments;

if let PathArguments::AngleBracketed(path_args) = args {
if let Some(GenericArgument::Type(ref t)) = path_args.args.first() {
if let Some(GenericArgument::Type(t)) = path_args.args.first() {
self.inner_result = is_result_type(t);
}
}
}
}

fn with_impl_trait(&mut self, imp: &TypeImplTrait) {
if let Some(TypeParamBound::Trait(ref bound)) = imp.bounds.first() {
if let Some(TypeParamBound::Trait(bound)) = imp.bounds.first() {
if let Some(segment) = bound.path.segments.first() {
if segment.ident == "Iterator" {
self.output_type = OutputType::Iter;

if let PathArguments::AngleBracketed(ref path_args) = segment.arguments {
if let Some(GenericArgument::AssocType(ref binding)) =
path_args.args.first()
{
if let PathArguments::AngleBracketed(path_args) = &segment.arguments {
if let Some(GenericArgument::AssocType(binding)) = path_args.args.first() {
if binding.ident == "Item" && is_result_type(&binding.ty) {
self.inner_result = true;
}
Expand Down Expand Up @@ -182,7 +180,7 @@ impl BlockBuilder {
return arg_tokens;
}

let pattern = format!("${}", var_name);
let pattern = format!("${var_name}");

if arg.contains(&pattern) {
quote! { #arg_tokens.replace(#pattern, &envs[#i].1) }
Expand Down
2 changes: 1 addition & 1 deletion shellfn-attribute/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn shell(attr: TokenStream, input: TokenStream) -> TokenStream {

if let Some(Stmt::Expr(
Expr::Lit(ExprLit {
lit: Lit::Str(ref program),
lit: Lit::Str(program),
..
}),
_,
Expand Down
6 changes: 3 additions & 3 deletions shellfn-attribute/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
use syn::{Type, TypePath};

pub fn is_result_type(typ: &Type) -> bool {
if let Type::Path(ref type_path) = *typ {
if let Type::Path(type_path) = typ {
is_path_to("Result", type_path)
} else {
false
}
}

pub fn is_unit_type(typ: &Type) -> bool {
if let Type::Tuple(ref tuple) = typ {
if let Type::Tuple(tuple) = typ {
return tuple.elems.is_empty();
}

false
}

pub fn is_vec_type(typ: &Type) -> bool {
if let Type::Path(ref type_path) = *typ {
if let Type::Path(type_path) = typ {
is_vec_type_path(type_path)
} else {
false
Expand Down
2 changes: 1 addition & 1 deletion shellfn-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.2.0"
authors = ["Marcin Sas-Szymanski <marcin.sas-szymanski@anixe.pl>"]
description = "Core functions for `shellfn` crate"
license = "MIT"
edition = "2018"
edition = "2024"

[lib]
doctest = false
Expand Down
2 changes: 1 addition & 1 deletion shellfn-core/src/execute/item.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::Error;
use crate::utils::{spawn, PANIC_MSG};
use crate::utils::{PANIC_MSG, spawn};
use std::error::Error as StdError;
use std::ffi::OsStr;
use std::str::FromStr;
Expand Down
2 changes: 1 addition & 1 deletion shellfn-core/src/execute/iter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::Error;
use crate::utils::{spawn, PANIC_MSG};
use crate::utils::{PANIC_MSG, spawn};
use itertools::Either;
use std::error::Error as StdError;
use std::ffi::OsStr;
Expand Down
2 changes: 1 addition & 1 deletion shellfn-core/src/execute/void.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::{Error, NeverError};
use crate::utils::{spawn, PANIC_MSG};
use crate::utils::{PANIC_MSG, spawn};
use std::ffi::OsStr;
use std::process::{Child, Output};

Expand Down
18 changes: 9 additions & 9 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ mod analyzes_return_type {
use super::*;

#[shell]
fn script(data: &str, exit_code: u32) -> impl Iterator<Item = u32> {
fn script(data: &str, exit_code: u32) -> impl Iterator<Item = u32> + use<> {
r#"
for V in $DATA; do
echo $V;
Expand Down Expand Up @@ -389,7 +389,7 @@ mod analyzes_return_type {
use super::*;

#[shell(no_panic)]
fn script(data: &str, exit_code: u32) -> impl Iterator<Item = u32> {
fn script(data: &str, exit_code: u32) -> impl Iterator<Item = u32> + use<> {
r#"
for V in $DATA; do
echo $V;
Expand Down Expand Up @@ -436,7 +436,7 @@ mod analyzes_return_type {
fn script(
data: &str,
exit_code: u32,
) -> impl Iterator<Item = Result<u32, BoxedError>> {
) -> impl Iterator<Item = Result<u32, BoxedError>> + use<> {
r#"
for V in $DATA; do
echo $V;
Expand Down Expand Up @@ -483,7 +483,7 @@ mod analyzes_return_type {
fn script(
data: &str,
exit_code: u32,
) -> impl Iterator<Item = Result<u32, BoxedError>> {
) -> impl Iterator<Item = Result<u32, BoxedError>> + use<> {
r#"
for V in $DATA; do
echo $V;
Expand Down Expand Up @@ -542,7 +542,7 @@ mod analyzes_return_type {
fn script(
data: &str,
exit_code: u32,
) -> Result<impl Iterator<Item = u32>, BoxedError> {
) -> Result<impl Iterator<Item = u32> + use<>, BoxedError> {
r#"
for V in $DATA; do
echo $V;
Expand Down Expand Up @@ -594,7 +594,7 @@ mod analyzes_return_type {
fn script(
data: &str,
exit_code: u32,
) -> Result<impl Iterator<Item = u32>, BoxedError> {
) -> Result<impl Iterator<Item = u32> + use<>, BoxedError> {
r#"
for V in $DATA; do
echo $V;
Expand Down Expand Up @@ -639,7 +639,7 @@ mod analyzes_return_type {
fn script(
data: &str,
exit_code: u32,
) -> Result<impl Iterator<Item = Result<u32, BoxedError>>, BoxedError>
) -> Result<impl Iterator<Item = Result<u32, BoxedError>> + use<>, BoxedError>
{
r#"
for V in $DATA; do
Expand All @@ -651,8 +651,8 @@ mod analyzes_return_type {
}

#[shell(cmd = "dummy_invalid_command_123")]
fn invalid_script(
) -> Result<impl Iterator<Item = Result<u32, BoxedError>>, BoxedError>
fn invalid_script()
-> Result<impl Iterator<Item = Result<u32, BoxedError>>, BoxedError>
{
r#"
invalid script iter
Expand Down
Loading