Skip to content

Commit

Permalink
Rename package from Chevy to Chevrons
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Doris committed Jan 29, 2025
1 parent 01b30a0 commit eff1ae9
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 100 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name = "Chevy"
name = "Chevrons"
uuid = "d9083b8b-98e7-4ee6-a2c7-6db47b61bf48"
authors = ["Christopher Doris <github.com/cjdoris>"]
version = "1.0.0"
Expand Down
66 changes: 33 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# » Chevy.jl
# » Chevrons.jl

[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![Test Status](https://github.com/cjdoris/Chevy.jl/actions/workflows/tests.yml/badge.svg)](https://github.com/cjdoris/Chevy.jl/actions/workflows/tests.yml)
[![Codecov](https://codecov.io/gh/cjdoris/Chevy.jl/branch/main/graph/badge.svg?token=1flP5128hZ)](https://codecov.io/gh/cjdoris/Chevy.jl)
[![Test Status](https://github.com/cjdoris/Chevrons.jl/actions/workflows/tests.yml/badge.svg)](https://github.com/cjdoris/Chevrons.jl/actions/workflows/tests.yml)
[![Codecov](https://codecov.io/gh/cjdoris/Chevrons.jl/branch/main/graph/badge.svg?token=1flP5128hZ)](https://codecov.io/gh/cjdoris/Chevrons.jl)

Your `friendly >> chevron >> based` syntax for piping data through multiple
transformations.
Expand All @@ -13,9 +13,9 @@ A [Julia](https://julialang.org/) package with all the good ideas from

Here is a simple example:
```julia-repl
julia> using Chevy, DataFrames, TidierData
julia> using Chevrons, DataFrames, TidierData
julia> Chevy.enable_repl() # magic to enable Chevy syntax in the REPL
julia> Chevrons.enable_repl() # magic to enable Chevrons syntax in the REPL
julia> df = DataFrame(name=["John", "Sally", "Roger"], age=[54, 34, 79], children=[0, 2, 4])
3×3 DataFrame
Expand All @@ -37,7 +37,7 @@ julia> df >> @filter(age > 40) >> @select(num_children=children, age)

Quick comparison with similar packages:

| Feature | Chevy.jl | [Chain.jl](https://github.com/jkrumbiegel/Chain.jl) | [Pipe.jl](https://github.com/oxinabox/Pipe.jl) |
| Feature | Chevrons.jl | [Chain.jl](https://github.com/jkrumbiegel/Chain.jl) | [Pipe.jl](https://github.com/oxinabox/Pipe.jl) |
| --- | --- | --- | --- |
| [Piping syntax](#getting-started) | ✔️ (`>>`) | ✔️ (`@chain`) | ✔️ (`\|>`) |
| [Side effects](#side-effects-with-) | ✔️ (`>>>`) | ✔️ (`@aside`) ||
Expand All @@ -53,15 +53,15 @@ Quick comparison with similar packages:
Click `]` to enter the Pkg REPL then do:

```
pkg> add Chevy
pkg> add Chevrons
```

### Getting started

Chevy exports a macro `@chevy` which transforms expressions like `x >> f(y, z)` into
Chevrons exports a macro `@chevrons` which transforms expressions like `x >> f(y, z)` into
`f(x, y, z)`. These can be chained together, so that
```julia
@chevy Int[] >> push!(5, 2, 4, 3, 1) >> sort!()
@chevrons Int[] >> push!(5, 2, 4, 3, 1) >> sort!()
```
is equivalent to
```julia
Expand All @@ -71,22 +71,22 @@ sort!(push!(Int[], 5, 2, 4, 3, 1))
In fact we can see exactly what it is transformed to with `@macroexpand`. This is
equivalent code but with intermediate results saved for clarity.
```julia-repl
julia> @macroexpand @chevy Int[] >> push!(5, 2, 4, 3, 1) >> sort!()
julia> @macroexpand @chevrons Int[] >> push!(5, 2, 4, 3, 1) >> sort!()
quote
var"##chevy#241" = Int[]
var"##chevy#242" = push!(var"##chevy#241", 5, 2, 4, 3, 1)
sort!(var"##chevy#242")
var"##chevrons#241" = Int[]
var"##chevrons#242" = push!(var"##chevrons#241", 5, 2, 4, 3, 1)
sort!(var"##chevrons#242")
end
```

### REPL integration

If you are using the Julia REPL, you can activate Chevy's REPL integration like
If you are using the Julia REPL, you can activate Chevrons's REPL integration like
```julia-repl
julia> Chevy.enable_repl()
julia> Chevrons.enable_repl()
```
This allows you to use this syntax from the Julia REPL without typing `@chevy` every
time. Use `Chevy.enable_repl(false)` to disable it again. The rest of the examples here
This allows you to use this syntax from the Julia REPL without typing `@chevrons` every
time. Use `Chevrons.enable_repl(false)` to disable it again. The rest of the examples here
will be from the REPL.

Also see [this tip](#startup-file) for automatically enabling the REPL integration.
Expand Down Expand Up @@ -174,15 +174,15 @@ julia> (

### Recursive usage

The `@chevy` macro works recursively, meaning you can wrap an entire module (or script
The `@chevrons` macro works recursively, meaning you can wrap an entire module (or script
or function or any code block) and all `>>`/`>>>`/`<<` expressions will be converted.

For example here is the first example in this README converted to a script:

```julia
using Chevy, DataFrames, TidierData
using Chevrons, DataFrames, TidierData

@chevy begin
@chevrons begin
df = DataFrame(name=["John", "Sally", "Roger"], age=[54, 34, 79], children=[0, 2, 4])
df2 = df >> @filter(age > 40) >> @select(num_children=children, age)
df2 >> println("data:", _)
Expand All @@ -193,7 +193,7 @@ end
Or the data manipulation step can be encapsulated as a function like so:

```julia
@chevy munge(df) = df >> @filter(age > 40) >> @select(num_children=children, age)
@chevrons munge(df) = df >> @filter(age > 40) >> @select(num_children=children, age)
```

### Pro tips
Expand All @@ -205,17 +205,17 @@ on a separate line for clarity. This also allows you to easily comment out indiv
transformations.

```julia
@chevy (
@chevrons (
df
# >> @filter(age > 40)
>> @select(nchildren=children, age)
>> @select(nchildren=children, age),
)
```

Or you can use `>>(x, y, z)` syntax instead of `x >> y >> z` like so:

```julia
@chevy >>(
@chevrons >>(
df,
# @filter(age > 40),
@select(nchildren=children, age),
Expand All @@ -225,27 +225,27 @@ Or you can use `>>(x, y, z)` syntax instead of `x >> y >> z` like so:
#### Startup file

You can add the following lines to your `startup.jl` file (usually at
`~/.julia/config/startup.jl`) to enable Chevy's REPL integration automatically:
`~/.julia/config/startup.jl`) to enable Chevrons's REPL integration automatically:

```julia
if isinteractive()
try
using Chevy
using Chevrons
catch
@warn "Chevy not available"
@warn "Chevrons not available"
end
if @isdefined Chevy
Chevy.enable_repl()
if @isdefined Chevrons
Chevrons.enable_repl()
end
end
```

Chevy has no dependencies so is safe to add to your global environment - then it will
Chevrons has no dependencies so is safe to add to your global environment - then it will
always be available at the REPL.

## API

See the docstrings for more help:
- `@chevy ...`: Transform and execute the given code.
- `chevy(expr)`: Transform the given expression.
- `Chevy.enable_repl(on=true)`: Enable/disable the REPL integration.
- `@chevrons ...`: Transform and execute the given code.
- `chevrons(expr)`: Transform the given expression.
- `Chevrons.enable_repl(on=true)`: Enable/disable the REPL integration.
54 changes: 27 additions & 27 deletions src/Chevy.jl → src/Chevrons.jl
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
module Chevy
module Chevrons

export chevy, @chevy
export chevrons, @chevrons

if VERSION v"1.11"
eval(Expr(:public, :enable_repl))
end

function enable_repl end

function chevy end
function chevrons end

macro chevy end
macro chevrons end

module Internals

import ..Chevy: enable_repl, chevy, @chevy
import ..Chevrons: enable_repl, chevrons, @chevrons

const tmp_index = Ref(0)

Expand All @@ -31,16 +31,16 @@ function tmpsym()
tmp_index[] = i + 1
Symbol(:tmp, i)
else
gensym(:chevy)
gensym(:chevrons)
end
end

"""
chevy(ex)
chevrons(ex)
Transforms an expression exactly the way [`@chevy`](@ref) does.
Transforms an expression exactly the way [`@chevrons`](@ref) does.
"""
function chevy(ex)
function chevrons(ex)
if (
ex isa Expr &&
ex.head == :call &&
Expand All @@ -51,10 +51,10 @@ function chevy(ex)
nargs = length(ex.args)
if nargs == 1
# nullary `>>()` not allowed
error("Chevy cannot handle zero-argument `$ex`")
error("Chevrons cannot handle zero-argument `$ex`")
elseif nargs == 2
# unary `>>(x)` is just `@chevy(x)`
return chevy(ex.args[2])
# unary `>>(x)` is just `@chevrons(x)`
return chevrons(ex.args[2])
elseif nargs == 3
# binary (lhs >> rhs) or (lhs << rhs) or (lhs >>> rhs) expression
op, lhs, rhs = ex.args
Expand All @@ -67,11 +67,11 @@ function chevy(ex)
end
# recurse on lhs and rhs
if op == :<<
lhs2 = chevy(rhs)
rhs2 = chevy(lhs)
lhs2 = chevrons(rhs)
rhs2 = chevrons(lhs)
else
lhs2 = chevy(lhs)
rhs2 = chevy(rhs)
lhs2 = chevrons(lhs)
rhs2 = chevrons(rhs)
end
# construct an answer block
ans = Expr(:block)
Expand Down Expand Up @@ -101,15 +101,15 @@ function chevy(ex)
return ans
elseif ex isa Expr
# otherwise recurse into expressions
return Expr(ex.head, map(chevy, ex.args)...)
return Expr(ex.head, map(chevrons, ex.args)...)
else
# otherwise no-op
return ex
end
end

"""
@chevy ex
@chevrons ex
Recursively replace `>>` chained function calls.
Expand All @@ -127,16 +127,16 @@ Also `>>>` can be used to keep the previous value.
- `x >>> f() >> g()` becomes `tmp = x; f(tmp); g(tmp)`
"""
macro chevy(ex)
return esc(chevy(ex))
macro chevrons(ex)
return esc(chevrons(ex))
end

"""
enable_repl(on::Bool=true)
Enable or disable REPL integration.
When enabled, all commands in the REPL are transformed by [`chevy`](@ref).
When enabled, all commands in the REPL are transformed by [`chevrons`](@ref).
You can call this in your `startup.jl` file.
"""
Expand All @@ -151,16 +151,16 @@ function enable_repl(on::Bool = true)
# if not, modify the list of default transforms
transforms = Base.REPL_MODULE_REF[].repl_ast_transforms
else
error("Cannot enable Chevy in the REPL.")
error("Cannot enable Chevrons in the REPL.")
end
filter!(is_not_chevy, transforms)
filter!(is_not_chevrons, transforms)
if on
pushfirst!(transforms, chevy)
pushfirst!(transforms, chevrons)
end
return
end

is_not_chevy(x) = x !== chevy
is_not_chevrons(x) = x !== chevrons

function sub_placeholder(x, f)
# directly substitute _/__/___/etc
Expand Down Expand Up @@ -233,7 +233,7 @@ function sub_specialcase(x, f)
end
# give up
error(
"Chevy cannot substitute into `$(truncate(f))`; expecting `_` or a function/macro call, indexing or property access.",
"Chevrons cannot substitute into `$(truncate(f))`; expecting `_` or a function/macro call, indexing or property access.",
)
end

Expand All @@ -247,4 +247,4 @@ end

end

end # module Chevy
end # module Chevrons
2 changes: 1 addition & 1 deletion test/aqua.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@testitem "Aqua" begin
using Aqua
Aqua.test_all(Chevy)
Aqua.test_all(Chevrons)
end
10 changes: 5 additions & 5 deletions test/integration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,36 @@ end

@testitem "DataFrames" setup = [Data] begin
using DataFrames
@test @chevy(
@test @chevrons(
Data.df1 >> subset(:age => age -> age .> 40) >>
select(:children => :number_of_children, :age)
) == Data.df1b
end

@testitem "DataFramesMeta" setup = [Data] begin
using DataFramesMeta
@test @chevy(
@test @chevrons(
Data.df1 >> @subset(:age .> 40) >> @select(:number_of_children = :children, :age)
) == Data.df1b
end

@testitem "DataFrameMacros" setup = [Data] begin
using DataFrameMacros
@test @chevy(
@test @chevrons(
Data.df1 >> @subset(:age > 40) >> @select(:number_of_children = :children, :age)
) == Data.df1b
end

@testitem "TidierData" setup = [Data] begin
using TidierData
@test @chevy(
@test @chevrons(
Data.df1 >> @filter(age > 40) >> @select(number_of_children = children, age)
) == Data.df1b
end

@testitem "Query" setup = [Data] begin
using DataFrames, Query
@test @chevy(
@test @chevrons(
Data.df1 >> @filter(__.age > 40)() >>
@map({number_of_children = __.children, __.age})() >> DataFrame()
) == Data.df1b
Expand Down
Loading

0 comments on commit eff1ae9

Please sign in to comment.