Giter Site home page Giter Site logo

boris's Introduction

Boris

A tiny, but robust REPL for PHP.

Code Climate Build Status

Announcement: I'm looking to add one or two additional collaborators with commit access. If you are actively involved in open source and have a GitHub profile for review, ping me on Twitter (@d11wtq) to express your interest. Experienced developers with active GitHub projects only.

Demo

Python has one. Ruby has one. Clojure has one. Now PHP has one, too. Boris is PHP's missing REPL (read-eval-print loop), allowing developers to experiment with PHP code in the terminal in an interactive manner. If you make a mistake, it doesn't matter, Boris will report the error and stand to attention for further input.

Everything you enter into Boris is evaluated and the result inspected so you can understand what is happening. State is maintained between inputs, allowing you to gradually build up a solution to a problem.

Note: The PCNTL function which is required to run Boris is not available on Windows platforms.

Why?

I'm in the process of transitioning away from PHP to Ruby. I have come to find PHP's lack of a real REPL to be frustrating and was not able to find an existing implementation that was complete. Boris weighs in at a few hundred lines of fairly straightforward code.

Usage

Check out our wonderful wiki for usage instructions.

Contributing

We're committed to a loosely-coupled architecture for Boris and would love to get your contributions.

Before jumping in, check out our Contributing contributing page on the wiki!

Contributing

We're using PHPUnit for testing. To run all the tests,

phpunit --bootstrap tests/autoload.php -c tests.xml

Core Team

This module was originally developed by Chris Corbyn, and is now maintained by Tejas Manohar, Dennis Hotson, and other wonderful contributors.

Copyright & Licensing

See the LICENSE file for details.

boris's People

Contributors

abackstrom avatar adamquaile avatar aleksandrbogdanov avatar chh avatar d11wtq avatar desarrolla2 avatar dhotson avatar donatj avatar filp avatar frosas avatar glensc avatar harto avatar imkrimerman avatar irongaze avatar lvancrayelynghe avatar mattketmo avatar pborreli avatar rogeriopradoj avatar scribu avatar simonmichael avatar siwinski avatar slkelevro avatar sserbin avatar taylorotwell avatar tejasmanohar avatar tobiassjosten avatar wogsland avatar zqueal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

boris's Issues

Won't run on PHP 5.5, Linux Mint 16

Hi all,

Tried the Phar and the git repo, can't get Boris to launch at all on Linux Mint 16, with PHP 5.5.3

PHP Warning:  pcntl_signal() has been disabled for security reasons in /home/josh/Apps/boris/lib/Boris/Boris.php on line 141
PHP Warning:  pcntl_fork() has been disabled for security reasons in /home/josh/Apps/boris/lib/Boris/Boris.php on line 148
PHP Notice:  fwrite(): send of 1 bytes failed with errno=32 Broken pipe in /home/josh/Apps/boris/lib/Boris/EvalWorker.php on line 205
PHP Fatal error:  Uncaught exception 'RuntimeException' with message 'Socket error: failed to write data' in /home/josh/Apps/boris/lib/Boris/EvalWorker.php:206
Stack trace:
#0 /home/josh/Apps/boris/lib/Boris/EvalWorker.php(88): Boris\EvalWorker->_write(Resource id #11, '?')
#1 /home/josh/Apps/boris/lib/Boris/Boris.php(171): Boris\EvalWorker->start()
#2 /home/josh/Apps/boris/bin/boris(16): Boris\Boris->start()
#3 {main}
  thrown in /home/josh/Apps/boris/lib/Boris/EvalWorker.php on line 206

That's my stacktrace when running bin/boris

Readline a required dependency?

On Ubuntu 12.4. After installing using

$ composer global require d11wtq/boris:*

I get the following error when I try to start:

$ boris
PHP Fatal error:  Call to undefined function Boris\readline_read_history() in /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/ReadlineClient.php on line 36
PHP Stack trace:
PHP   1. {main}() /home/itbrig/.composer/vendor/d11wtq/boris/bin/boris:0
PHP   2. Boris\Boris->start() /home/itbrig/.composer/vendor/d11wtq/boris/bin/boris:16
PHP   3. Boris\ReadlineClient->start() /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/Boris.php:157
PHP Notice:  fwrite(): send of 1 bytes failed with errno=32 Broken pipe in /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/EvalWorker.php on line 205
PHP Stack trace:
PHP   1. {main}() /home/itbrig/.composer/vendor/d11wtq/boris/bin/boris:0
PHP   2. Boris\Boris->start() /home/itbrig/.composer/vendor/d11wtq/boris/bin/boris:16
PHP   3. Boris\EvalWorker->start() /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/Boris.php:171
PHP   4. Boris\EvalWorker->_write() /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/EvalWorker.php:88
PHP   5. fwrite() /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/EvalWorker.php:205
PHP Fatal error:  Uncaught exception 'RuntimeException' with message 'Socket error: failed to write data' in /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/EvalWorker.php:206
Stack trace:
#0 /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/EvalWorker.php(88): Boris\EvalWorker->_write(Resource id #11, '\x03')
#1 /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/Boris.php(171): Boris\EvalWorker->start()
#2 /home/itbrig/.composer/vendor/d11wtq/boris/bin/boris(16): Boris\Boris->start()
#3 {main}
  thrown in /home/itbrig/.composer/vendor/d11wtq/boris/lib/Boris/EvalWorker.php on line 206

After installing readling using...

$ apt-get install php5-readline

...all works as expected. Are we depending on readline? Maybe readline should be listed as a dependency in composer.json?

UTF characters

There seems to be some problems when feeding non ascii characters to boris. I have several db passwords with characters like ž,ą,č and similar that are impossible to enter/paste.

Ubuntu 12.04 x86_64, Boris @ b3ac553

boris> echo "xyz"; should append new line?

I type ...

[1] boris> $x = "hello world";
 → 'hello world'
[2] boris> echo $x;
hello world[3] boris> exit;

and actually would expect something like:

[1] boris> $x = "hello world";
 → 'hello world'
[2] boris> echo $x;
hello world
[3] boris> exit;

Does this makes sense?

Use stream_socket_* functions instead of socket_* ?

The preferred way to do socket operations in PHP is to use the stream_socket_ functions which are provide a more convenient API, and are available by default. The socket_ functions are not available when PHP is compiled without "--enable-sockets".

I've written a blog post about this:
http://christophh.net/2012/07/24/php-socket-programming/

I'm happy to provide a patch for this if needed, I just want to check if usage of the socket_ functions is intentional.

This is a great project and absolutely what I was looking for usage in my own framework!

more feedback when PCNTL functions are missing (e.g. with default OSX php)

git clone git://github.com/d11wtq/boris.git
cd boris
./bin/boris

and that's it, nothing, no prompt.

PHP works pretty well, I use drush all the time.

Any idea what could be wrong?

$ php -v
PHP 5.3.26 (cli) (built: Jul  7 2013 19:05:08)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies

Could not exit from boris

Using latest version

[16:29 @ ~/www/boris] $ git lg
fe10592 - (HEAD, origin/master, origin/HEAD, master) Merge pull request #55 from abackstrom/more-objectvars (6 weeks ago) Chris 'Chippie' Corbyn
[16:30 @ ~/www/boris] $ git pull
Already up-to-date.
[16:32 @ ~/www/boris] $ boris
[1] boris> :
[1]     *> ;
PHP Parse error:  syntax error, unexpected ':' in phar:///usr/local/bin/boris/lib/Boris/EvalWorker.php(133) : eval()'d code on line 1
PHP Stack trace:
PHP   1. {main}() /usr/local/bin/boris:0
PHP   2. require() /usr/local/bin/boris:9
PHP   3. Boris\Boris->start() phar:///usr/local/bin/boris/bin/boris:15
PHP   4. Boris\EvalWorker->start() phar:///usr/local/bin/boris/lib/Boris/Boris.php:171

Parse error: syntax error, unexpected ':' in phar:///usr/local/bin/boris/lib/Boris/EvalWorker.php(133) : eval()'d code on line 1

Call Stack:
    0.0001     245288   1. {main}() /usr/local/bin/boris:0
    0.0005     259968   2. require('phar:///usr/local/bin/boris/bin/boris') /usr/local/bin/boris:9
    0.0017     433744   3. Boris\Boris->start() phar:///usr/local/bin/boris/bin/boris:15
    0.0034     509576   4. Boris\EvalWorker->start() phar:///usr/local/bin/boris/lib/Boris/Boris.php:171

 → false
[2] boris> ^C^C^C

[2] boris> exit;
[3] boris> exit;
[4] boris> exit;
[5] boris> exit;
[6] boris> exit;
[7] boris> exit;
[8] boris> exit;
[9] boris> exit;
[10] boris> exit;
[11] boris> exit;
[12] boris> exit;
[13] boris> ^C^C^C^C^C

[13] boris> 

[13] boris> ^C^C^C

[13] boris> ^C^C^C^C

[13] boris> ^C^C^C^C

[13] boris> 

[13] boris> exit;
[14] boris> exit;
[15] boris> exit;

Variable variable eval issue

Ran into this issue when playing around with variable variables in boris. Also tested w/ php -a without any issue:

[1] boris> $foo = 'huzaaaah!';
 → 'huzaaaah!'
[2] boris> $bar = 'foo';
 → 'foo'
[3] boris> $$bar;
 → 'huzaaaah!'
[4] boris> $baz = 'oo';
→ 'oo'
[5] boris> ${'f'.$baz};
PHP Parse error:  syntax error, unexpected end of file in /usr/local/Cellar/boris/1.0.2/lib/Boris/EvalWorker.php(133) : eval()'d code on line 1

Parse error: syntax error, unexpected end of file in /usr/local/Cellar/boris/1.0.2/lib/Boris/EvalWorker.php(133) : eval()'d code on line 1
→ NULL

Question regarding inspectors

When using the inspectors they're isolated to the output of the current command (as far as I can tell). The inspectors are instantiated once; but when a command causes an error, a new inspector is added to a new thread (I think).

I've just scanned the code so far as to finding out how Boris works, but is the following possible: An inspector that lives throughout the whole Boris session, keeping track of notices, errors, and commands?

Thanks for your time, Boris is very interesting 👍

Environment Variable Setting

I feel like this should be simple but I can't figure out the right approach to get it to work. My code, when running via Apache, needs an environment variable specified for the Oracle oci8 PHP library:

DYLD_LIBRARY_PATH = /opt/instantclient_11_2

This works fine via Apache, but if PHP starts up without that variable set I get errors immediately and this messes with boris.

I've tried and failed setting this using putenv() in a ~/.borisrc file and also using $boris->setLocal() which I assumed wouldn't work anyway.

What approach should I use to have boris start up with this environment variable set?

Thanks in advance!

Tag a release version

I'm creating a homebrew-php formula, and it would be nice to peg it to a release.

Access returned values from `include`

Currently:

$ boris
[1] boris> $a = include 'myfile.php';

$

Expected similar to:

$ php -a
Interactive shell

php > $a = include 'myfile.php';
php > var_dump($a);
string(5) "VALUE"
php > ^D⏎
$

Implicit semicolon

I guess you've considered this already, but it'd be really nice to have an implicit semicolon on newline. You could always split to multiple lines with trailing \ or such.

Wish: .phar version

Hi, it would be just swell if you made a .phar version.

Good work creating this!

XDebug Integration

Is there any plan on making Boris work with xdebug as phpsh (somewhat) does?

Remove magic number for fatal error exit code

https://github.com/d11wtq/boris/blob/master/lib/Boris/EvalWorker.php#L9

While this works for all PHP versions I've tested Boris in (and nobody else has told me it doesn't), it does seem a bit fragile. The better thing to do would be to work out this exit code on startup.

On Boris->start():

1. Fork a child and wait for it to exit.
2. In the child, call a function known not to exist.
3. In the parent, capture the error code into a variable.

This captured error code should be the fatal exit code it uses thereon in.

PHP Fatal error on launch

Hi there

I get the following error when I start boris up.

PHP Fatal error: Call to undefined function Boris\readline_read_history() in /Users/neil/work/boris/lib/Boris/ReadlineClient.php on line 36

Fatal error: Call to undefined function Boris\readline_read_history() in /Users/neil/work/boris/lib/Boris/ReadlineClient.php on line 36
prod03:boris neil$ PHP Fatal error: Uncaught exception 'RuntimeException' with message 'Socket error: failed to write data' in /Users/neil/work/boris/lib/Boris/EvalWorker.php:118
Stack trace:
#0 /Users/neil/work/boris/lib/Boris/Boris.php(95): Boris\EvalWorker->start()
#1 /Users/neil/work/boris/bin/boris(9): Boris\Boris->start()
#2 {main}

thrown in /Users/neil/work/boris/lib/Boris/EvalWorker.php on line 118

Fatal error: Uncaught exception 'RuntimeException' with message 'Socket error: failed to write data' in /Users/neil/work/boris/lib/Boris/EvalWorker.php:118
Stack trace:
#0 /Users/neil/work/boris/lib/Boris/Boris.php(95): Boris\EvalWorker->start()
#1 /Users/neil/work/boris/bin/boris(9): Boris\Boris->start()
#2 {main}

thrown in /Users/neil/work/boris/lib/Boris/EvalWorker.php on line 118

What am I doing wrong?

ColoredInspector and custom object handling

The ORM I work with daily has a getData() method which returns an array representation of a model. I've hacked up ColoredInspector, replacing calls to get_object_vars() with a new method _objectVars(). This lets me customize object output based on the type of object I'm inspecting, substituting getData for get_object_vars when inspecting models.

Can something similar be built into ColoredInspector to make this customization more maintainable? An overridable _objectVars() public method on ColoredInspector would do the trick, or a private method that runs user-specified variable-extracting callbacks.

more robust printing in EvalWorker?

Hi, thanks for this very useful tool.

While working on a client's wordpress setup, I encountered the following issue:

[1] boris> require_once("wp-config.php");
[2] boris> "dump this?";
[3] boris> // no output ...;

However, after I changed EvalWorker->start to use fwrite(STDOUT, ...) instead of printf, i.e.

-            printf(" → %s\n", $this->_inspector->inspect($__result));
+            fwrite(STDOUT, sprintf(" → %s\n", $this->_inspector->inspect($__result)));
+            flush();

I no longer have issue. I haven't had a chance to troubleshoot exactly which plugin or configuration option causes the issue but if you don't see any harm I'll send a PR. Otherwise I could dig in further once I get some time.

Support executing boris by php executable specified in environment variable.

Drush supports reading in the php executable to run with using an environment variable (named $DRUSH_PHP). This is useful if you have multiple copies of PHP on your system and is easier than switching your $PATH environment variable.

Drush does this as follows:

if [ -n "$DRUSH_PHP" ] ; then
  # Use the DRUSH_PHP environment variable if it is available.
  php="$DRUSH_PHP"
else
  # On MSYSGIT, we need to use "php", not the full path to php
  if [ -n "$MINGW" ] ; then
    php="php"
  else
    # Default to using the php that we find on the PATH.
    # We check for a command line (cli) version of php, and if found use that.
    # Note that we need the full path to php here for Dreamhost, which behaves oddly.  See http://drupal.org/node/662926
    php="`which php-cli 2>/dev/null`"

    if [ ! -x "$php" ]; then
      php="`which php 2>/dev/null`"
    fi

    if [ ! -x "$php" ]; then
      echo "ERROR: can't find php."; exit 1
    fi
  fi
fi

... then later...

exec "$php" $php_options "$SCRIPT_PATH" --php="$php" --php-options="$php_options" "$@"

... you can see all the code in the Drush repository on Github

Make the history searchable

Just like in a regular shell, where you can search the history by hitting ctrl-r. Best solution I've found is to use grep in a second shell, which isn't ideal.

Hitting CTRL-C should kill any child, but keep the REPL open.

If I do something like this in IRB or Pry, I can hit CTRL-C to stop it.

[1] pry(main)> (0..Float::INFINITY).each{|n| puts n.even? ? "Tick" : "Tock"; sleep 1}
Tick
Tock
Tick
Tock
^CInterrupt: 
from (pry):1:in `sleep'
[2] pry(main)> 

I should be able to do the same in Boris:

boris> for ($i=0;; ++$i) { printf(($i % 2) ? "Tock\n" : "Tick\n"); sleep(1); }
Tick
Tock
Tick
Tock
^C

Rather than just exiting the entire REPL, Boris should signal trap this and terminate the child that is currently working.

Issue with kill signal

Hello, I've a small issue when sending a SIGINT while running Boris. This is what happens when I Ctrl-C:

[1] boris> PHP Warning:  stream_select(): unable to select [4]: Interrupted system call (max_fd=3) in /tmp/boris/lib/Boris/EvalWorker.php on line 158

Warning: stream_select(): unable to select [4]: Interrupted system call (max_fd=3) in /tmp/boris/lib/Boris/EvalWorker.php on line 158

I haven't really investigated yet, but do you know why is this happening? (I'm running php 5.4.12 on OSX)
Thanks.

Tab completion and reflection methods?

Just discovered Boris. Very nice! After using Ruby's Pry my first thought was on tab completion. As a simple test, dropping in the readline_completion_function from this php repl got immediate PHP completions which is quite helpful:

https://github.com/ErikDubbelboer/php-repl

The inline documentation like and other reflection methods are neat as well. Any thoughts on combining the best of the 3?

boris all around cool repl
php-repl tab completions
php_repl reflection methods

Thanks!

Reliance on pcntl_fork

Unable to run Boris because of a reliance on a non default extension PCNTL.

PHP Fatal error:  Call to undefined function pcntl_fork() in boris/lib/Boris.php on line 38

Would be great if this extension could be avoided, other-words it should be listed as a dependency in the README with directions on how to recompile PHP with PCNTL enabled.

Readline seems to be breaking

Hitting the "up" button sometimes shows a mangled version of the previous line, often after printing the previous command. Here's an example

[1] boris> $result = ''
[1]     *> ;
 → string(0) ""
[2] boris> $result += 'foo';
 → int(0)
[3] boris> echo $result;
0[4] boris> $result .= 'foo';   // Hit "up" here to get command #2 

Resulted in two variables getting set, one named $result and one named $resultt. I think the problem is the 0 at the beginning of the line complicating things.

set_exception_handler in startup-required code acts buggy

When a startup-required file contains a set_exception_handler call, it sometimes causes problems with boris' own error handler.

Steps to reproduce:

Make up a require-file

$ cat requireme.php
<?php

function test_exception_handler(Exception $e){
    echo 'Hi, I am a default required exception handler: '.$e->getMessage();
}
set_exception_handler('test_exception_handler');

Then run with it

$ boris -r requireme.php 

first line somehow does not do it. It needs to be non-throwing thing

[1] boris> $v = 1;
 → 1

And here we go:

[2] boris> throw new Exception('Hi!');
PHP Fatal error:  Maximum function nesting level of '100' reached, aborting! in EvalWorker.php on line 170
PHP Stack trace:
PHP   1. Boris\EvalWorker->delegateExceptionHandler()
PHP   2. call_user_func() /home/syn/Code/boris/lib/Boris/EvalWorker.php:170
<...part repeating EvalWorker->delegateExceptionHandler call expunged>

But if we set the handler by hand right here:

[3] boris> set_exception_handler('test_exception_handler');
 → array(
  0 => object(Boris\EvalWorker)(

  ),
  1 => 'delegateExceptionHandler'
)

It all works just fine

[4] boris> throw new Exception('Hi!');
Hi, I am a default required exception handler: Hi!
[5] boris> 

Reloading Boris

Hey there,

Would love to see a feature to reload boris while inside. I'm going to see if I can write it myself, but was curious about what key combo I should bind it to. I'm leaning towards Ctrl + R.

The feature itself will basically just do the same as exiting and restarting, to bring in the code changes to the environment you've required with boris -r. Nothing fancy, basically just doing the same as Ctrl + D except instead of exiting entirely, it starts up again.

I couldn't find much else in the issues list, although my search-fu is weak, has this been discussed anywhere?

Keep up the awesome work :)

Josh

possibly cross platform, multi-threaded support for your brilliant idea

<?php
/*
 A threaded REPL for PHP ... 
*/

/*
 A working context to evaluate user code
*/
class Context extends Worker {  
    public $console;
    public $shutting;

    /*
     Requires a console, sets shutting flag
    */
    public function __construct($console) {
        $this->console = $console;
        $this->shutting = false;
    }

    /*
     Extracts from object store into an array suitable for extract()
    */
    public function manifest() {
        $data = array();
        foreach ($this as $key => $value)
            $data[$key] = $value;
        return $data;
    }

    /*
     Catches fatal errors
    */
    public function run() {
        register_shutdown_function(
            array(&$this, "shutting"));
    }

    /*
     Notifies anyone waiting on console so execution may continue
    */
    public function shutting() {
        $this->shutting = true;
        $this->console->synchronized(function($console){
            $console->notify();
        }, $this->console); 
    }
}

/*
 A container for an expression ( or block, if someone extends it )
*/
class Expression extends Stackable {
    public $code;
    public $result;
    public $exception;

    public function __construct($code) {
        $this->code = $code;
    }

    public function run() {
        try {
            /*
             I think you need to return in eval code to get result out ...
            */
            $this->result = eval(
                sprintf(
                    "extract(\$this->worker->manifest());\r\n".
                    "%s",
                    $this->code
                )
            );
        } catch (Exception $ex) {
            $this->result = $ex;
            $this->exception = true;
        }
        /*
         Notify the waiter that we are done executing ...
        */
        $this->worker->console->synchronized(function(){
            $this->worker->console->notify();
        });
    }
}

/*
 Used a synchronization object which 
    all contexts have access to 
    no matter what happens to any other objects
*/
class Console extends Stackable {
    public function run() {}
}

/*
 Passed around ...
*/
$console = new Console();
$continue = true;

do {
    echo "console> ";
    /*
     Read a line, this is simplistic ... multi-line would be good ...
    */  
    while ($line = fgets(STDIN)) {
        /*
         Check for leaving ...
        */
        if (trim($line) == "exit" || 
            trim($line) == "quit") {
            exit(0);
        }

        /*
         Check if we need a new worker
        */
        if (!@$worker || $worker->shutting) {
            $worker = new Context($console);
            $worker->start();
        }

        /*
         Tell the worker to execute the code
        */
        $worker->stack(
            $express = new Expression($line)
        );

        /*
         Wait for notification that the job is done
        */
        if (!isset($express->result)) {
            $console->synchronized(function($console){
                $console->wait();
            }, $console);
        }

        /*
         Output exception/result
        */
        if ($express->exception)
            echo $express->result->getTraceAsString();  
        else if ($express->result)
            var_dump($express->result);
        echo "\r\nconsole> ";
    }
} while($continue);
?>

You can obviously do a better job of implementing the features of your idea ... something to think about maybe ...

Requires only pthreads .. I'm not sure how you would go about catching CTRL+C, or if that is appropriate for a multi-threaded, multi-platform version ...

kudos on the idea btw, very cool indeed 👍

Tidy warnings twice during launch

The following is what I see each time I load boris (as installed through homebrew).

[21:58] Bryson@zeus  ~ :$ boris
PHP Warning:  Module 'tidy' already loaded in Unknown on line 0

Warning: Module 'tidy' already loaded in Unknown on line 0
[1] boris>

I have installed the following packages through homebrew also, as using OS X 10.8.5's bundled PHP versions (5.3.x) does not work.

brew install php55 --homebrew-apxs --with-debug --with-fpm --with-gmp --with-homebrew-openssl --with-homebrew-libxslt --with-imap --with-pgsql --with-thread-safety --with-tidy --without-apache --without-mysql
brew install php55-couchbase php55-intl php55-mcrypt php55-tidy php55-xdebug php55-xcache libpqxx boris

boris still works as expected for me so far, other than these warnings.

Add \slash commands

Exiting out of boris (heh) is hard. In most REPLs, there is a shortcut way to quickly exit the interpreter. Commonly this is \q, but could also be \exit or just plain exit.

The best way I've found to cleanly leave boris is by entering "exit;", but this fails if you've ever hit an exception - you need to type out "exit(99);" or similar to cause the interpreter to really exit.

I think the best solution would be to support \q and \exit as exit commands, and \help to explain the above. A \reload would be really nice as well, to prevent the common case of needing to exit then re-run to reload code changes.

Haven't yet poked around in the interpreter cycle to see where this would best fit, but it would be a nice addition to a great little REPL. Happy to take a swing at it if you're interested and can provide a starting point for how best to integrate with the existing code flow.

Dumping out current environment?

Hey there!

Love boris, it makes PHP development and exploration of a codebase an absolute dream. The one thing I feel like that its missing is a feature that may not even be possible to implement, but I thought I'd ask regardless.

How difficult would it be to be able to export/dump the PHP that has been typed into the REPL? Say, function definitions and the like? Not necessarily expressions per se (although to be honest, even just a straight "transcript" dump would be brilliant), but function, class and method definitions that have been typed in.

Perhaps even a way of defining "This is a new session for this environment, start recording what I'm doing" and the "End that session and export the code out to a PHP file". The reason I'd love something like that is it would enable true interactive development through the REPL itself, rather close to how Lisp REPLs are implemented.

I'm going to take a poke through Boris' code and have a look at whether it'd be possible anyway, but I thought I'd ask!

BORIS won't start

I get the following error when I try to start it. I cloned the repo, cd'ed and tried to run it.

Dinos-MacBook-Pro:bin dinoangelov$ ./boris

Fatal error: Call to undefined function Boris\pcntl_signal() in /Users/dinoangelov/Library/Developer/boris/lib/Boris/Boris.php on line 110

Assigning an anonymous function. Is this a bug?

jcromero@hipatia:~/src/boris$ ./bin/boris
[1] boris> $f = function() {};
PHP Parse error: syntax error, unexpected end of file in /home/jcromero/src/boris/lib/Boris/EvalWorker.php(133) : eval()'d code on line 1
PHP Stack trace:
PHP 1. {main}() /home/jcromero/src/boris/bin/boris:0
PHP 2. Boris\Boris->start() /home/jcromero/src/boris/bin/boris:16
PHP 3. Boris\EvalWorker->start() /home/jcromero/src/boris/lib/Boris/Boris.php:171
→ NULL
[2] boris>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.