magefile / mage

a Make/rake-like dev tool using Go
https://magefile.org
Apache License 2.0
4.05k stars 249 forks source link

Add autocomplete #289

Open nikitavoloboev opened 4 years ago

nikitavoloboev commented 4 years ago

Would be great if you could type mage and press tab to autocomplete all the possible commands. Or start typing command mage st and on tab it would autocomplete to the nearest matching command.

Is it possible to add this to mage itself or it has to be added in some other way?

natefinch commented 4 years ago

This has to be done by the terminal/os and is pretty fiddly, which is why I've hesitated to take on that maintenance burden.

ghost commented 4 years ago

I'm currently using the zsh make plugin to provide autocomplete of build targets. The build targets for a particular project have become complicated though, and I'm thinking of moving to Mage to make development and maintenance easier. Not having autocomplete would be a huge burden, since the naming of the build targets are (by design) long, explicit, but organized such as:

kubernetes.render
kubernetes.apply
kubernetes.clean

docker.hadolint
docker.tag
docker.build

here's the script to do Makefile completion

https://github.com/zsh-users/zsh/blob/master/Completion/Unix/Command/_make

The only burden Mage has over Make is identifying mage files. But since that's already defined as:

A mage file is any regular go file marked with a build target of “mage” and in package main.

It only means that parsing many files in the repo root would be needed. I think parsing the first 10 lines of file would probably be enough to identify which files are mage files or not, for performance reasons.

ghost commented 4 years ago

I also found this that might make it easier: https://github.com/posener/complete/tree/master

ghost commented 4 years ago

oh, target imports would also be another burden, though it's explained here: https://magefile.org/importing/

ghostsquad commented 4 years ago

@natefinch could you point me at a method that would return a list of targets? I can see if I can submit a PR for this.

ghostsquad commented 4 years ago

It seems I could write something fairly simple, at least for oh-my-zsh by using mage -l, e.g. https://github.com/sawadashota/go-task-completions

The problems I see right now are that mage -l is fairly slow, so it would likely be pretty frustrating, especially when you compare it to autocomplete speed of the make script for zsh.

Additionally, it's not required that //+build mage files exist at the project root, or that you have a compiled binary.

Related situations to this I found:

247

283

In order to solve the performance problem, we could leverage the compiled binary if it exists, but since the name of that binary is unknown, and could likely change from project to project (even on the same developer machine), we'd need the global mage to pass thru to the compiled binary (if it exists). See #295 for that.

ghostsquad commented 4 years ago

for the time being though, the autocomplete script could do something like this:

if [ -x ./mage ]; then
  out=$(./mage -l)
else
  out=$(mage -l)
fi

echo "${out}" | tail -n +2 | awk '{ print $1 }'

This makes some assumptions though that cannot be easily controlled by the user.

ghost commented 4 years ago

so looking at this more, completions, though folks have said is a "simple dsl" is hard to wrap my mind around. I'm wondering if instead, mage switched to using https://github.com/spf13/cobra which supports generating completions for zsh and bash natively.

ghostsquad commented 4 years ago

so, I figured out the script, naively assuming that the built binary is ./mg

#compdef _mg mg

function _mg {
    _complete_commands () {
        if [ -x ./mg ]; then
            compadd $(./mg -l | tail -n +2 | awk '{ print $1 }')
        fi
    }

    _arguments '1: :_complete_commands'
}

So, to make this work for both a binary and not, I think there needs to be some way of knowing what the binary name is, such as an environment variable. If that's not present, fallback to running mage -l.

@natefinch thoughts on this?

ghostsquad commented 4 years ago

haha, just found out that mg is a text editor.

man mg
...
mg -- emacs-like text editor
johnboyes commented 4 years ago

I haven't used it yet but https://github.com/iwittkau/mage-select offers bash completion, worth looking into I reckon

jpopadak commented 4 years ago

I haven't used it yet but https://github.com/iwittkau/mage-select offers bash completion, worth looking into I reckon

Downside is this also uses mage -l which can cause it to be slower.

But if its include in Mage and mage command is used (not compiled binary), maybe there is a way to short circuit the logic during reading of the magefiles? Or would that be too early?

ghostsquad commented 4 years ago

@jpopadak that's why I filed #295 such that mage can passthru to the compiled binary and not be required to read/parse in order to autocomplete.

sluedecke commented 3 years ago

https://github.com/magefile/mage/issues/113 has some completion scripts which might solve this one

sheldonhull commented 2 years ago

I've asked a related question on https://github.com/magefile/mage/discussions/368

I was thinking of generating some vscode tasks, but also have thought about integration https://github.com/c-bata/go-prompt.

I'm thinking of:

Some prompt action like the bit cli would be pretty awesome if we can figure it out.

DavidGamba commented 2 years ago

There is an alternative approach where you use the binary to generate completions directly. You can handle all your completions in Go and just detect if bash is calling the go binary in completion mode or in execution mode.

Once you do that you actually get built in completions that are never out of date. I have a Youtube video with my CLI parser which does just that, but the same approach can be adapted to leverage the existing CLI parser mage is using. https://youtu.be/1ZGyIkC5shM

josegonzalez commented 2 years ago

Having mage generate completions directly would be great. This is how mitchellh/cli works (through an install command that can probably be genericized) which is used by all of the hashicorp tooling.

Penthious commented 1 year ago

Any traction on this?

technicallyty commented 1 year ago

bumping, anyone ever get something going on their machine?

mloskot commented 8 months ago

Since I've started using Mage as an actual Bash replacement and I'm defining large number of targets-as-commands with variety of arguments, and aliases too, I'm thankful for the awesome mage -l and mage -h target commands. However, shell completion would be awesome^2.

Would you indeed agree that the best approach seems to be that Mage could generates the completion itself? And, that there are two options to achieve it

  1. https://github.com/posener/complete suggested by someone in https://github.com/magefile/mage/issues/289#issuecomment-599090578
  2. https://github.com/DavidGamba/go-getoption suggested by @DavidGamba in https://github.com/magefile/mage/issues/289#issuecomment-1014620850

correct?

Any disadvantages of making the one or the other Mage's dependency?

sheldonhull commented 8 months ago

Mage development has stalled to my knowledge due to other priorities from the original creator. Still great to use as is but I doubt you'll see significant features until that changes.

Try Mage-select. It's a great alternative to invoking interactively.

mloskot commented 8 months ago

@sheldonhull

Mage development has stalled to my knowledge

I'm sad to say I have noticed. I still hope future of Mage is bright - I love it.

Try Mage-select.

Yeah, I am going to, definitely.