stecman / symfony-console-completion

Automatic tab-key completion for Symfony console application options, arguments and parameters
MIT License
420 stars 26 forks source link

How to call this command via "php www/index.php" #4

Closed TomasVotruba closed 9 years ago

TomasVotruba commented 9 years ago

Hi, I would like to use this component but I don't understand it's installation.

I found this gist where you edit composer's source code.

I've added this command as any other, e.g. Doctrine ones to Nette (similar as adding commands in Symfony).

So I call them like this:

$ php www/index.php orm:generate-entities

How I understand this package is that it should help me to suggest command names.

So when working correctly, when I type:"

$ php www/index.php orm

and hit tab, it should suggest all command who's name starts with "orm".


Is there any possibility to use this without editing composer`s internal files? If so, how to?

Thank you

stecman commented 9 years ago

Is there any possibility to use this without editing composer's internal files?

Yes, I've now written a Composer plugin to add BASH completion. It's a pretty hacky solution, and a bit fragile since it relies on a specific behaviour in Composer, but it works without modifying Composer's source.

stecman commented 9 years ago

Regarding the main part of your question, once you've added the completion command to your application, you need to register it in your BASH shell session to have it work. The following generates and runs the BASH code to do this:

# The `_completion` command is what the CompletionCommand adds.
# NOTE: This isn't the best solution in your case (see below)
eval $(php www/index.php _completion --generate-hook)

The main problem I can see with your command line examples is that they conflict with the way BASH completion works. When completion is requested, BASH chooses a completion handler based on the program name - the first word on the command line; completing for php www/index.php will look for a completion handler registered to php. This is because BASH's completion functionality is designed for use with programs on your PATH, where only the program name matters and the location of the file does not. Additionally, even if you do drop the php part, BASH will never try to figure out if www/index.php means /foo/www/index.php or /bar/www/index.php.

Due to this caveat, the command I mentioned above would register a handler for the string www/index.php, and not a handler tied to the actual path of the file. The easiest way to get around this limitation/design is to set an alias for your script, and set up completion on the alias:

# ~/.bash_profile:
alias foo-console='php /foo/www/index.php'
eval $(foo-console _completion --generate-hook --program foo-console)

Then reload you bash profile and completion should work:

$ foo-console [tab]
TomasVotruba commented 9 years ago

Thank you for reply!

Ad plugin, where exactly is "bash profile"?

I use "oh my zsh" and I've tried with no success:

~/.bash_profile
~/.zshrc

So far I didn't get any further.

stecman commented 9 years ago

Ah right - the fact you are using ZSH is important; the completion systems in BASH and ZSH are completely different and are not interchangeable. This module currently can only generate a hook for BASH's completion system, though as the actual implementation of the module is not shell-specific, it is possible to plug it into other completion systems.

I'm not a ZSH user myself, but I've done a bit of research and fiddling to come up with a hook for using this module with ZSH. The code below goes in place of the eval line I mentioned before and will go in your ~/.zshrc file. You'll need to replace /usr/bin/beam with the path to your program, and _beam with an appropriate function name:

# ~/.zshrc

function _beam {
    # Emulate BASH's command line contents variable
    local -x COMP_LINE="$words"

    # Emulate BASH's cursor position variable, setting it to the end of the current word.
    local -x COMP_POINT
    (( COMP_POINT = ${#${(j. .)words[1,CURRENT]}} ))

    # Run the `_complete` command, turning the resulting lines of output into an array
    RESULT=("${(@f)$( /usr/bin/beam _completion )}")
    STATUS=$?;

    # Bail out if PHP didn't exit cleanly
    if [ $STATUS -ne 0 ]; then
        echo $RESULT;
        return $?;
    fi;

    compadd -- $RESULT
};

compdef _beam /usr/bin/beam;

Based on this hook, I've added instructions for using that Composer plugin with ZSH. I've been thinking about adding ZSH support to this module for a while, so I might integrate this hook code given a little more testing.

TomasVotruba commented 9 years ago

I see. I was about to use this extension on one specific php project. I first thought it's mainly Symfony\Console based (php ) extension, so any programmer could use it just by downloading the project.

Now I understand it's more complicated and that it's not possible to do it php-way only at the moment. So it won't use it in the near future.

Thank you for work though, it help me to understand bit more of composer and code completion in bash.