Hi there,

I've been playing around with the idea of allowing drush to work in interactive mode, that is, entering a "drush shell" (drushsh? :P) and dispatch commands within the same "drush session". I've written up a little piece of code to start proofing the concept.

The interactive shell will implement some built-in commands only applicable within the interactive session, as an example: 'exit', 'cwd' and 'cd' are included.

Example usage:

jonhattan@jengibre:~$ drush cli
drush> help
[...]

drush> help status
View the Drupal version and DB credentials for the current site.

drush> cwd
Current working dirctory is: /home/jonhattan

drush> cd /var/www/drupal-6.13/sites/drupal6-dev
Current working dirctory is: /var/www/drupal-6.13/sites/drupal6-dev

drush> status
  PHP configuration : /etc/php5/cli/php.ini
  Drupal Root       : /var/www/drupal-6.13
  Drupal version    : 6.13
  Site Path         : sites/drupal6-dev
  [...]

drush> exit
jonhattan@jengibre:~$ 

Code is in my cvs sandbox => http://cvs.drupal.org/viewvc.py/drupal/contributions/sandbox/jonhattan/d...

Comments

moshe weitzman’s picture

nifty. this might be a simpler way to do autocomplete, BTW

jonhattan’s picture

I've added readline support (http://us3.php.net/manual/en/book.readline.php). This includes command history, autocompletion and those bash tricks (ctrl+w,...).

Some points about readline:
* it is gpl licensed and php is currently not compatible with gpl, so debian does not include readline support in php.
* there's an alternative implementation (bsd licensed) known as libedit or editline. Ubuntu builds php --with-libedit. Although it is buggy.
* dotdeb.org guys provide a php --with-readline version that I am using in debian.
* this question is also addressed at #437568: Autocomplete awesomeness for drush on comments #41 and #50.

About autocompletion:
* @moshe and other drush maintainers: do you consider changing whitespaces by other character in commands? It is a headache for autocompletion and no advantage at all to use whitespaces. Changing for ":" (I dont know the english name for it) would be very nice. BTW this is the symfony cli syntax :)
* current code has some extra logic to allow for whitespaces autocompletion but it works partially and I think it can't fully work at all (try running with --debug to see the autocompletion options).
* I think same problem with whitespaces is at #437568: Autocomplete awesomeness for drush.

About this command:
* I'm developing it as a "external" command (no modification of drush core) but I'd love to see drush entering in interactive mode when running with no options instead of dumping the ever growing help text. What do you think about it?

Anonymous’s picture

subscribing

jonhattan’s picture

New changes:
* allow to press <enter> with no command. Previously if enter was pressed the session finished because of readline.
* allow to continue interacting if previous command failed (not found, etc) by cleaning the error context.
* added quit command in addition to exit.

moshe weitzman’s picture

I like this. It reminds me of git-sh - http://github.com/rtomayko/git-sh/tree/master. Would be great to borrow any relevant ideas we can from that project.

I think I am OK with this becoming the default command if one just types `drush`. The help command would then only be accessible with `drush help`. Or by entering this interactive mode and then saying `help.

I'm not too familiar with readline, nor do i know how this behaves on installs that don't have it. i definately do not want to add a ton of support requests from those people. if this is an unsolvable problem, lets keep the current behavior for `drush` and add this as just a `drush cli` command.

I also think I am OK with getting rid of whitespace in commands and replacing with :. One annoyance with that character is that it requires a shift button press also (USA keyboard). A semicolon would be slightly easier.

I'd love some feedback on this file and on my replies above.

jonhattan’s picture

I'll look at git-sh. My inspiration is trac command line tool.

Both : and ; requires a shift press also in spanish keyboards. I suggest using hyphens (-). I've oppened a new issue for this: #550522: Change white spaces in commands by another symbol.

readline:
* If no readline support we could fallback to help command.
* A FAQ about readline can be added to the doc.

changes in new rev:
* cli_drush_init() check if readline is available.
* Changed the mainloop to test locally if given command is valid instead of relying on drush_main (more speed).

As a side note, look at this funny/annoying behaviour:

jonhattan@jengibre:/var/www/drupal-6.13/sites/drupal6-dev$ drush cli
matching function for this command: drush_cli_cli
matching function for this command: drush_sql_cli
drush> status
matching function for this command: drush_core_status
 [....]
drush> exit
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 241
Server version: 5.0.51a-24+lenny1 (Debian)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> exit
Bye

As you can see I've added a print "matching functions for this command" in drush_invoke (includes/command.inc).

It is intended to have other matching functions in addition to _validate, _pre and _post? As I'm not sure about it I've not filled a bug report.

EDIT: i post a separate issue for that #562178: drush_invoke: is intended to have other matching functions than _validate, _pre and _post?

vingborg’s picture

I've been working on something very similar for some time, and my conclusion is that readline is problematic. For decent support of various platforms (*nix, windows) and php packages/versions, it can't be relied upon. At least such a "console" command should fall back to some basic readline emulation, IMO.

But this is very, very cool.

intuited’s picture

Since the problems with readline have now come up in two different issues (this one and #437568: Autocomplete awesomeness for drush), and aren't really directly related to either of them, I've made a separate issue for it: #562888: The readline library. I wasn't really sure how to set the status, since I just wanted to create an area to centralize the discussion of problems, solutions, and workarounds that has sprung up on on two different issue threads and isn't really directly related to either of them.

jonhattan’s picture

Those are the features I have been working on:

1. fallback to using a basic input (fgets) if readline is not available, as suggested by vingborg.
vinborg: do you now of a better way of doing it and try to make work [TAB] and/or cursors ?

2. rework of command parsing in drush_cli_cli()

3. I tried to rework `cd` command to allow for:

drush> cd /var/wwww/drupal-6.13                           // bootstrap to this drupal root
drush [/var/www/drupal-6.13]> cd example.com              // bootstrap to sites/example.com (DRUSH_BOOTSTRAP_DRUPAL_SITE)
drush [/var/www/drupal-6.13#example.com]> cd example.net  // bootstrap to sites/example.net (DRUSH_BOOTSTRAP_DRUPAL_SITE)

Some changes to drush_bootstrap() and drush_bootstrap_validate() are needed to allow for "rebootstrapping". I hacked it to try to 'de-bootstrap' drush to DRUSH_BOOTSTRAP_DRUPAL_ROOT by reseting some drush contexts and drupal's global variables. No problem found when de-bootstrapping from DRUSH_BOOTSTRAP_DRUPAL_SITE and DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION, but found a impassable wall at DRUSH_BOOTSTRAP_DRUPAL_DATABASE: it is not possible to de-bootstrap because drupal uses a static variable in db_set_active(). It is so for drupal 5 and 6. I've not entered into detail for drupal7 but perhaps with PDO this is not a limitation to allow for rebootstrapping. I decided to drop this branch and didn't examine if limitations for drupal7 do exist.

The target of that branch was to allow to manage several sites within the same session of drush. It'd be possible to do some multisite work in drupal 5 and 6 if we avoid bootstrapping beyond DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION. That is: no database work at all... just `drush dl` and no much more.
Do you think this is interesting to work this only for drupal 7?

While writting those lines I've realized that other approach to this target is possible by using drush_backend_invoke(). Aditionally this will allow us to use different drupal roots (platforms in Aegir's terminology). No changes to drush core for "rebootstrapping", just use a different process each time....... but using a different process each time is not much of an advantage for the interactive mode as it will be somehow equivalent to just do bash autocompletion (in the worst case a full bootstrap will be done for each command). Even more, additional logic will be needed in the cli command because it can't rely on drush bootstrap to find if the directory we wanna change to is a valid drupal root or a valid site, etc.
It would be of interest to use a pool of subprocesses, one for each platform / site we have bootstrapped and allow to switch to one or other and perform commands. Each subprocess would be a `drush cli` able to communicate with the master cli, that is the one responsible of handling the subprocesses pool. I don't know if it is even possible or just a fiction. My next iteration over cli will be on that direction. Sorry for this aloud thinking :)

A last usage note: at present `cd` and other cli subcommands (bootstrap-status, available-sites) have been removed. You can run `drush cli` as with any other command, providing --root and --uri or starting in a drupal root/site path. It will bootstrap to max available.

EDIT: this is the direct link to last version of the code: http://cvs.drupal.org/viewvc.py/drupal/contributions/sandbox/jonhattan/d...

mariomaric’s picture

Subscribing.

greg.1.anderson’s picture

Just noticed this issue. I don't think that drush needs to rewrite bash in order to get a drush cli. You can accomplish much of this by simply defining some aliases:

alias d='drush'
alias help='drush help'
alias status='drush status'

etc.

The way I would implement 'drush cli' would be to dynamically generate a bashrc file that sets the prompt to "drush>", defines an alias for every drush command, and then launches "bash" with the custom bashrc file. That would be less code and more functionality, because you'd get all of bash's built-in features, like $((42*17)) and all sorts of obscure stuff that some people 'just use' if it's already there.

I think jonhattan's cli could be very useful to DOS users, I think cygwin is an even better solution, as cygwin has bash... Also, there are some good ideas in #9, but you'd have to find good ways to regenerate the contexts, or one command would pollute the next. I think re-bootstrapping every time is easier, and the performance hit isn't such a big deal. More power to you if you want to spend the effort, but I don't think the gains are worth it.

Maybe if I'm up late at night I'll whip up a proof-of-concept for DrupalCon. Should only be a few lines of code...

greg.1.anderson’s picture

I included a prototype drush cli using bash at Comment #21 of #768092: Suggestions to improve core-directory command.

We also have the drush shell project; I sent the maintainer some email and directed him here. (note though that he already abandoned this project in favor of using bash customizations.)

greg.1.anderson’s picture

Status: Needs work » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.