jeff-hykin / better-shell-syntax

💾 📦 ♻️ An improvement to the shell syntax for VS Code
MIT License
52 stars 4 forks source link

Highlight nested contexts in shellscript #5

Open texastoland opened 4 years ago

texastoland commented 4 years ago

Your scripts are really clever but the syntax doesn't highlight expansions nested in double-quoted strings like the original ("foo ${bar} $(baz)"). A feature I want even more that's also missing from the original is highlighting inside single-quoted aliases:

# everything in aliases is code
# zsh aliases accept a -g flag
# other shells' aliases should be supported too
alias system-color-scheme='echo ${(L)$(defaults read -g AppleInterfaceStyle 2> /dev/null):-light}'
jeff-hykin commented 4 years ago

Yeah, this is an issue, there's a few other interpolation issues too. I'll be working on fixing them when writing the grammar completely. The alias idea sounds really cool, I'm not sure if aliases can be used outside of a command context though, like in an conditional or file redirection.

It might be awhile before I'm able to rewrite the grammar though

texastoland commented 4 years ago

I wrote a grammar for Sublime Text years ago. I can at least test if not help! I didn't understand about aliases? I imagined it being a recursive context just like quoted expansions and substitutions.

ntarox commented 4 years ago

+1, it's excellent as-is but would love to have nested expansions highlighted i.e. "foo_${var}_bar"

jeff-hykin commented 4 years ago

@texastoland Thats great to hear, this repo is currently using a beta of a library that makes it's it a lot easier to write grammars, but familiarity with the old grammars will help a lot. Part of the reason I'm not making as many changes is because this repo (along with the similar perl, dockerfile, c, and go syntaxes) is using an out-of-date version of the library.

I'm working on finalizing and publishing the library this summer, and then converting this repo to it so that contributions are easier.

@texastoland the comment about aliases: command context

alias aCommand="echo hello world"

argument context

alias anArgument="hello world"
echo $anArgument

I'm not certain that an alias is always used as a command

texastoland commented 4 years ago
alias anArgument="hello world"
echo $anArgument

I'm not certain that an alias is always used as a command

That doesn't work right? In zsh you could do:

# expand when surrounded by whitespace
alias -g  anArgument='hello=world'
echo  anArgument  # > hello=world
echo "anArgument" # > anArgument
      anArgument  # >
echo $anArgument  # >
echo $hello       # > world

As a general rule highlighting it as a substitution (like $(...)) would be preferable to string highlighting.

jeff-hykin commented 4 years ago

That doesn't work right? In zsh you could do:

Yeah, or I'd be surprised if it did, I didn't check it. I'm just saying I'm not sure if it's always used as a command. Maybe it can be an operator, or a value inside of an evaluation, I'd have to find some documentation on it. I'd also need to check edgecases such as how this (below) is handled:

alias thing="echo" hello

Even small grammar modifications can be a real pain unless you find documentation saying "this format is the only way it is allowed", cause otherwise you have to think of every possible way it could be used instead of just adding support for the most common case.

That zsh option is surprising, I didn't think arguments could be expanded like that without a $

I also didn't realize the alias could have the -g. I've mostly be using the bash/shell documentation as a reference for the syntax although I use zsh

texastoland commented 4 years ago
alias thing="echo" hello

That isn't an edge case but the way builtin commands work (those are technically two different things but for simplicity's sake):

# define one and print the other
alias thing="echo" hello
# > bash: alias: hello: not found
export thing="echo" hello
declare -p thing hello
# > declare -x thing="echo"
# > bash: declare: hello: not found

That zsh option is surprising, I didn't think arguments could be expanded like that without a $

Those are parameters. Aliases are used like functions.

Aliases are macros. They expand literally in place. In Bash they expand if preceded only by whitespace. In zsh there are flags for expansion between whitespace (global aliases) or as a command depending on file extension (suffix aliases). Even wrapped in quotes they still get evaled. In Bash they must be valid commands.

For argument's sake in zsh you could do:

# no secret yet
alias -g secret='secret is $secret`
echo secret
# > secret is
read-secret # from a file or URL 
echo secret
# > secret is 12345

In practice that doesn't happen. Because they're evaled aliases are at least equivalent to double quotes. From a user perspective it's more useful to treat them as commands.