psysh icon indicating copy to clipboard operation
psysh copied to clipboard

Tab completion breaks paste

Open tgr opened this issue 9 years ago • 13 comments

Pasting this:

array(
        1
);

(middle line indented with two tabs) into the shell (Psy Shell v0.6.0-dev (PHP 5.5.9-1ubuntu4.11 — cli)) gives

>>> 
Display all 3299 possibilities? (y or n) 
>>> array(
... 
Display all 3299 possibilities? (y or n) 
... 1
... );
=> [
     1
   ]

Somehow it should detect that the content is being pasted and ignore tabs.

For longer text, sometimes pasting is interrupted by the "Display... " line and the rest of the pasted input does not appear at all.

tgr avatar Nov 04 '15 11:11 tgr

This is an issue with readline and libedit (the libraries used to get user input by almost every command line thing ever, including PsySH) and I don't know that there's a way to fix it other than disabling tab completion :(

http://superuser.com/questions/926028/completion-when-pasting-bash-command-beginning-with-tabs

bobthecow avatar Nov 04 '15 13:11 bobthecow

You could try to disable autocompletion when on a line which only contains tab characters; it is apparently possible with the Python readline bindings at least. Or simple replace tabs with spaces. Or detect the number of characters buffered but not transmitted to readline yet, and guess whether it's a paster based on that.

tgr avatar Nov 12 '15 10:11 tgr

As far as I can tell, it's not possible with the PHP readline bindings. The tab characters seem to trigger tab completion immediately, before I have access to them on the readline buffer :-/

bobthecow avatar Nov 12 '15 16:11 bobthecow

It actually looks like the results returned here are from a bunch of psysh Matchers - the T_OPEN_TAG is a legitimate hasMatched for (for example) FunctionsMatcher, ClassNamesMatcher and ConstantsMatcher. The potential matches include things like echo, empty, etc.

This isn't a case of readline being difficult. If it was, you would be able to set rl_completion_over (or completion_over in case you are setting it using readline_info) to a value other than 0.

krageon avatar Aug 30 '17 09:08 krageon

I made a pull request to fix this.

krageon avatar Aug 30 '17 10:08 krageon

Oh! I forgot to update this diff. This is fixed as of v0.8.11 (the readline way) if you use readline (not libedit) and a reasonably modern terminal app. Enable useBracketedPaste in your psysh config and enjoy :)

https://github.com/bobthecow/psysh/releases/tag/v0.8.11

bobthecow avatar Aug 30 '17 15:08 bobthecow

Cool! I'll close the PR in that case. Perhaps it is a good idea to close this issue as well, to prevent future confusion :)

I am curious why it's readline-only though, I'll dig around a little after lunch.

krageon avatar Aug 31 '17 10:08 krageon

This is fixed as of v0.8.11 (the readline way) if you use readline (not libedit) and a reasonably modern terminal app. Enable useBracketedPaste in your psysh config and enjoy :)

When I paste code with two or more tabs to psysh, I get the same behavior that @tgr mentioned in the issue description (see below). I'm running v0.8.17 and I have useBracketedPaste enabled. @bobthecow, can you please elaborate on what you meant by a modern terminal app? I'm running Ubuntu 17.10 and I use zsh. How can I check if psysh is using readline instead of libedit? I have php-readline installed.

If I try to paste the code below (middle line indented with two tabs) into the shell:

array(
        1
);

I get:

$ psysh
Psy Shell v0.8.17 (PHP 7.1.13-1+ubuntu17.10.1+deb.sury.org+1 — cli) by Justin Hileman
>>> array(
... 
Display all 3004 possibilities? (y or n) 
... 

If I set tabCompletion to false, pasting the code works but in the middle of the pasted code a list of files from the working directory is displayed:

>>> array(
... 
.babelrc           .editorconfig      .github            .jshintrc          .travis.yml        apigen.neon        CODE_OF_CONDUCT.md Gruntfile.js       license.txt        package-lock.json  phpunit.xml        sample-data        uninstall.php     
.codeclimate.yml   .git               .gitignore         .scrutinizer.yml   .wordpress-org     assets             composer.json      i18n               node_modules       package.json       README.md          templates          vendor            
.codecov.yml       .gitattributes     .idea              .stylelintrc       apigen             CHANGELOG.txt      composer.lock      includes           none               phpcs.xml          readme.txt         tests              woocommerce.php   
... 1
... );
=> [
     1,
   ]

rodrigoprimo avatar Jan 25 '18 17:01 rodrigoprimo

Can you paste the output of \Psy\info()?

bobthecow avatar Jan 25 '18 18:01 bobthecow

>>> \Psy\info()                                                                                                                                                                                                                                                                           => [
     "PsySH version" => "v0.8.17",
     "PHP version" => "7.1.13-1+ubuntu17.10.1+deb.sury.org+1",
     "default includes" => [],
     "require semicolons" => false,
     "error logging level" => 32767,
     "config file" => [
       "default config file" => "~/.config/psysh/config.php",
       "local config file" => null,
       "PSYSH_CONFIG env" => false,
     ],
     "updates" => [
       "update available" => false,
       "latest release version" => "v0.8.17",
       "update check interval" => "weekly",
       "update cache file" => "~/.config/psysh/update_check.json",
     ],
     "pcntl" => [
       "pcntl available" => true,
       "posix available" => true,
     ],
     "readline" => [
       "readline available" => true,
       "readline enabled" => true,
       "readline service" => "Psy\Readline\Libedit",
       "readline library" => "EditLine wrapper",
     ],
     "history" => [
       "history file" => "~/.config/psysh/psysh_history",
       "history size" => null,
       "erase duplicates" => null,
     ],
     "docs" => [
       "manual db file" => null,
       "sqlite available" => true,
     ],
     "autocomplete" => [
       "tab completion enabled" => true,
       "custom matchers" => [],
       "bracketed paste" => false,
     ],
   ]

I have 'useBracketedPaste' => true in my config file but I see that bracketed paste is set to false in the \Psy\info(). Maybe this is related with the issue that I'm having? Thanks for looking into this.

rodrigoprimo avatar Jan 25 '18 18:01 rodrigoprimo

Yeah. It’s because you’ve got libedit rather than GNU readline :(

bobthecow avatar Jan 25 '18 20:01 bobthecow

Oh, php-readline installs libedit and not readline. I wasn't aware of the licensing issues between PHP and GNU readline. Thanks for your help.

rodrigoprimo avatar Jan 25 '18 21:01 rodrigoprimo

Just for the record, the new(ish) edit command is totally awesome and mostly fixes this issue for people who are stuck on libedit.

tgr avatar Jun 22 '18 16:06 tgr