Git Product home page Git Product logo

The splatting operator '@' cannot be used to reference variables in an expression. '@trigger' can be used only as an argument to a command. To reference variables in an expression use '$trigger' about powershell HOT 8 OPEN

deadcoder0904 avatar deadcoder0904 commented on May 20, 2024
The splatting operator '@' cannot be used to reference variables in an expression. '@trigger' can be used only as an argument to a command. To reference variables in an expression use '$trigger'

from powershell.

Comments (8)

SteveL-MSFT avatar SteveL-MSFT commented on May 20, 2024 2

There seems to be two possible options here and both might be bucket 3 in terms of a breaking change.

  • since we have a specific error here, we could simply treat the "splatting" as literal instead of returning an error
  • if the variable being splatting doesn't exist, then it becomes literal to avoid accidental splatting

from powershell.

MartinGC94 avatar MartinGC94 commented on May 20, 2024 1

The parsing seems to already handle other special characters like: ls @Test\ or ls @Test* so it doesn't seem unreasonable to think it should handle . as well, considering that it isn't possible to access a member from a splatted variable anyway.

from powershell.

MartinGC94 avatar MartinGC94 commented on May 20, 2024 1

A reddit thread indicates that there's also been some parsing regression between 5.1 and 7 when = is used in the string. Where npm config set @scope:registry=https://www.myregistry.com/ works in 5.1 but not 7 see: https://www.reddit.com/r/PowerShell/comments/1b85las/npm_works_different_in_51_vs_7/ for more details.

from powershell.

237dmitry avatar 237dmitry commented on May 20, 2024

Try to escape command line arguments of pnpm:

pnpm --% dlx @trigger.dev/cli@latest init -k tr_dev_1213241234zxcz -t https://cloud.trigger.dev

from powershell.

mklement0 avatar mklement0 commented on May 20, 2024

To add to @237dmitry's comment:

  • Indeed, use of --%, the stop-parsing token is an option, but note that it comes with many limitations, notably the inability to reference PowerShell variables.

  • The problem is that @ - unlike in other shells - is a metacharacter at the start of arguments in PowerShell, used for splatting - that's what the error message is referencing.

    • Additional characters that you may not expect to be metacharacters are { } , ; ` (see full list below).
  • Therefore a @ (or any other metacharacter) that is to be used verbatim at the start of an argument must either inside a quoted string or must be individually escaped with `, the so-called backtick, PowerShell's escape character.

Applying the latter technique to your command (note how only the initial @ need be escaped, though escaping both would work too):

# Note the ` before the first @
pnpm dlx `@trigger.dev/cli@latest init -k tr_dev_1213241234zxcz -t https://cloud.trigger.dev

# Alternative with a quoted string
# Note the ` before the first @
pnpm dlx '@trigger.dev/cli@latest' init -k tr_dev_1213241234zxcz -t https://cloud.trigger.dev

The list of PowerShell metacharacters in argument-parsing mode is:

<space> ' " ` , ; ( ) { } | & < > @ #

Note:

  • Of these, < > @ # are only special at the start of an argument.
  • Situationally, . (dot) requires escaping too, namely if the argument can syntactically be interpreted as accessing a variable's property (e.g., Write-Output $env:computername.csv outputs nothing - see this answer).
  • If you want a $ to be treated verbatim rather than refer to a variable or subexpression, you must escape it too.
  • For a complete overview of how unquoted command arguments are parsed in PowerShell, see this answer.

from powershell.

deadcoder0904 avatar deadcoder0904 commented on May 20, 2024

I think this should work by default as countless npm modules will start from @ as more packages are used.

I'd rather want @ to work than remember to escape it.

Otherwise, I have to open another terminal with Git Bash which is not convenient.

from powershell.

mklement0 avatar mklement0 commented on May 20, 2024

Good point, @MartinGC94.

There's several awkward behaviors around argument mode - both with native PowerShell commands and native (external) programs, and it may be worth revisiting all of them in the context of a focus feature request, so they can be addressed with a single change, which will at least technically amount to breaking changes.

Using the case at hand as an example:

Here, the issue is that the .dev part of @trigger.dev is considered a property access, which triggers the error message:

  • Without splatting, such a property access does work, and is useful in isolation:

    • E.g., Write-Output $HOME.Length works and reports the value of $HOME.Length, i.e. the count of characters in the value of the $HOME variable.
  • In a compound argument, it technically still "works", but exhibits behavior that is unlikely to be helpful in practice:

    • E.g., Write-Output $HOME.Length/foo is the same as Write-Output $HOME.Length /foo, i.e. whatever follows the property reference becomes a separate argument.

Given that @trigger.dev never makes sense as a property access, it is reasonable to fall back to treating it as a verbatim string, especially in native program calls.

Arguably, also treating $HOME.Length/foo as "$($HOME).Length/foo" makes more sense than the current behavior.

However, even in native program calls treating an isolated argument such as @trigger verbatim is not an option, because splatting does work with external programs (often seen with @args), albeit only meaningfully with arrays rather than hashtables.

Currently, something like cmd /c echo @foo effectively passes no arguments to the external program, if no $foo variable exists.

Perhaps @foo is a rare use case and having subsequent characters, such as a filename extension (e.g, @foo.txt) is the typical use case, in which case falling back to verbatim use is safe - and perhaps, pragmatically speaking, that is therefore sufficient.

But the point is that all these behaviors and edge cases need to spelled out and agreed upon in detail before potentially making changes.


See also:

from powershell.

mklement0 avatar mklement0 commented on May 20, 2024

Yes, it looks like WinPS - sensibly - falls back to treating the whole argument like an expandable string ("@scope:registry=https://www.myregistry.com/"), whereas PS Core expands @scope:registry to the empty string, and therefore passes only =https://www.myregistry.com:

@scope:registry is technically the splatted form of $scope:registry, which is technically a valid variable reference, using namespace variable notation, and "splatting" @scope:registry alone results in no argument getting passed, in both editions, because $scope:registry happens not to exist.

In both editions, however, referencing existing variables via namespace variable notation does work, so that something like @env:PATH does splat, and - because a [string] is enumerably and therefore triggers array-based splatting - passes the individual characters in $env:PATH as separate arguments (this behavior is fundamentally questionable).

When you follow a "splatted" namespace variable reference with a non-variable-name character other than = (e.g, #, % or !), the whole argument is (sensibly) interpreted like an expandable string in both editions.

However - in PS Core only - a subsequent = still triggers the splatting, and passes the = and whatever follows it as a separate argument. In the case at hand, since $scope:registry doesn't exist, the @scope:registry part effectively expands to no argument, and =https://www.myregistry.com/ is passed as the only argument resulting from the original token.

from powershell.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.