elvish icon indicating copy to clipboard operation
elvish copied to clipboard

Use prefix syntax for global wildcard modifiers

Open xiaq opened this issue 5 years ago • 5 comments

There are two different types of wildcard modifiers; local ones only apply to one wildcard, while global ones actually apply to the entire wildcard pattern. They are both written after a wildcard - this is appropriate for local modifiers, but awkward and confusing for global modifiers. For example, to generate all *.go files except main.go, one needs to write *[but:main.go].go.

It's much better to write global modifiers as a prefix of the entire wildcard pattern; for example [but:main.go]*.go, or, after #1018 is merged [type:dir]*.

xiaq avatar May 31 '20 13:05 xiaq

Having looked at how global modifiers are currently implemented I like this proposal. On the one hand it would simplify that logic. On the other it's going to require complicating the parser to allow an "index" to appear where it currently doesn't make any sense. Too, what if the first non-modifier char isn't a wildcard? What if there are no wildcards at all? For example, [type:dir]/tmp.

krader1961 avatar May 31 '20 21:05 krader1961

Note this sentence in the documentation of global wildcard modifiers:

On the other hand, you must add it after a wildcard, instead of after the entire pattern: put /.cpp[nomatch-ok] unfortunately does not do the correct thing. (This will probably be fixed.)

That raises the question, in light of this issue, whether global modifiers should be allowed as a prefix, suffix, or both. In the past @xiaq seemingly felt it made more sense to allow global modifiers as a pattern suffix even if the final pattern component was not a wildcard. This issue suggests prefix form might be preferable.

It's much better to write global modifiers as a prefix of the entire wildcard pattern; for example [but:main.go]*.go

I agree with the sentiment but believe making global modifiers a suffix of the pattern is preferable to making them a prefix. I think **/x*[type:dir] reads better than [type:dir]**/x*.

krader1961 avatar Jun 08 '20 04:06 krader1961

This issue also begs the question of what it means to apply a global modifier to a pattern that has no wildcard tokens. Such as [type:dir]/a/path or /a/path[type:dir]. If allowed it means an exception will be raised if /a/path is not a directory. Which is technically the same as asking what happens if [type:dir]/a/path/* does not expand to any directories but makes me uneasy. The latter case would obviously require using the [nomatch-ok] global modifier if you don't care that the wildcard pattern does not match any directories. The former case seems slightly nonsensical. If you don't really care if the literal path is not a directory why use [nomatch-ok][type:dir]/a/path. That would, theoretically, result in the path being elided from the command arguments. But is supporting that a good idea?

krader1961 avatar Jun 08 '20 05:06 krader1961

I'm curious what your current thinking is, @xiaq, given that you have marked this as a blocking issue for the next, 0.16, release. This seems like the sort of change that requires a lot of discussion even if the changes to the parser that allow the [...] indexing syntax at the head of a token are straightforward. Tagging this for the 0.16 release suggests you believe some of the ambiguities I mentioned earlier are not a problem. At least so far as they will be handled by Elvish in a reasonable manner. I'm curious what you think those behaviors will be.

krader1961 avatar Mar 15 '21 04:03 krader1961

I agree with the sentiment but believe making global modifiers a suffix of the pattern is preferable to making them a prefix. I think **/x*[type:dir] reads better than [type:dir]**/x*.

Suffix syntax doesn't work for cases like **/x*b[type:dir] because [type:dir] will be parsed as an index to b. So prefix only.

This issue also begs the question of what it means to apply a global modifier to a pattern that has no wildcard tokens. Such as [type:dir]/a/path or /a/path[type:dir]. If allowed it means an exception will be raised if /a/path is not a directory. Which is technically the same as asking what happens if [type:dir]/a/path/* does not expand to any directories but makes me uneasy. The latter case would obviously require using the [nomatch-ok] global modifier if you don't care that the wildcard pattern does not match any directories. The former case seems slightly nonsensical. If you don't really care if the literal path is not a directory why use [nomatch-ok][type:dir]/a/path. That would, theoretically, result in the path being elided from the command arguments. But is supporting that a good idea?

That'd be a parse error.

xiaq avatar Jul 18 '21 16:07 xiaq