Comments (7)
You can probably just use exit
or die
, but if you really want to throw
something, this is basically what I did for the coffeescript port:
class SystemExit extends Exception {
function __construct($usage) {
exit($usage . PHP_EOL);
}
}
throw new SystemExit("test");
from docopt.php.
Sorry, this reply ended up turning into a bit of a braindump. I think I understand my the issue a bit better now as a result though, so thanks for poking me into action!
Commence dumpage in 3... 2... 1...
The main issue is I want it to be possible, though not necessary, to take full responsibility for error output and exiting in the calling code. For example, in python, you can have it both ways and the client code is nice, clean, idiomatic python:
# this will exit with invalid input, but without a backtrace:
args = docopt(blah blah blah)
# full control of output and status:
try:
args = docopt(doc)
except DocoptExit:
print "Whatever I want, whenever I want, but it still quits if I don't"
exit 9
# lovely!
You can suppress or modify output(1), have a custom exit status, whatever you like.
In PHP, die()
doesn't give you this option as it's uncatchable. The SystemExit
exception ticks all the boxes, but we don't get access to it in PHP
. I'm trying to think of the smallest possible way to emulate the flexibility the python version has with the least impact on client code.
My first version of the PHP port looked like this:
<?php
try {
$args = Docopt\docopt($doc);
}
catch (Docopt\ExitException $ex) {
echo $ex->getMessage();
exit(1);
}
If you didn't catch it, you got backtraces on your command line, which is no good, but you did get full control of the output and status.
The next attempt looked - actually, looks, at the time of writing - like this:
<?php
$args = Docopt\docopt($doc);
if ($arguments === false)
exit(1);
The catch
is moved into the Docopt\docopt()
function. You can control the output, but only if you subclass Docopt\Handler
and override handleExit()
or use output buffering. I absolutely hate this "solution", hence why I'm furtively seeking a better one!
Anyway, the best I have so far is to add a flag to docopt to disable auto-exiting, then change the return of Docopt\docopt()
to a result object that implements ArrayAccess
. I'm not overly fond of this idea, but I'm more fond of it than my previous two attempts and it does seem to support my main requirement: that the client can, but does not have to, assume full control of the exiting and output:
<?php
// auto-exit and auto-output if input is invalid:
$result = Docopt\docopt($doc);
// don't auto-exit; output and status are the calling code's responsibility:
$result = Docopt\docopt($doc, array('exit'=>false));
if (!$result->success) {
echo "Nah, didn't work";
exit($result->status ?: 1);
}
echo $result['-q'];
1^ This is not 100% true - the exit that happens for --version
and --help
can be caught but they still emit output before they raise. I don't want to mimic this caveat.
from docopt.php.
@shabbyrobe You noticed that DocoptExit works neat in python, but it is not in public API/docs—because I am unsure if anyone would ever like to catch this and mess with exit message/status.
So I would suggest echo "error message"; echo $printable_usage; exit(1)
to be the replacement for DocoptExit.
from docopt.php.
It's more about being able to control where exit
happens. It's kind of an offshoot of the old "only one return" holy war. I'm not necessarily in that camp - I do like my guard clauses - but having exit
hidden off in a library doesn't suit my preference for guard clauses being obviously visible up the top of a block.
I really like docopt.py's way of doing it - the exits happen if you let them, but they don't have to. I've thought more about it and I think the response object example at the bottom of the previous post is the way to go. A response object will still behave just like a dictionary if it implements ArrayAccess
, so the change will be transparent. I can also corral it down the bottom, so integrating changes from the python implementation will remain a fairly one-to-one affair.
I guess I really just want to make sure the PHP library gives me the option of working the way I want without imposing that on anybody else.
from docopt.php.
I've pushed a version of this. The object returned by Docopt\docopt()
behaves exactly like an array:
<?php
$args = \Docopt\docopt($doc);
echo $args['--quiet'].PHP_EOL;
foreach ($args as $k=>$v) {
echo $k.": ".json_encode($v).PHP_EOL;
}
But it also does exactly what I want (not that my code would look quite this terrible):
<?php
$args = \Docopt\docopt($doc, array('exit'=>false));
if (!$args->success) {
echo $args->output.PHP_EOL;
}
else {
echo $args['--quiet'].PHP_EOL;
}
exit($args->status);
I'm going to leave the issue open just for the time being to make sure it's front and center that this may not be 100% finalised, but I think by talking through it here I've arrived at a good balance.
from docopt.php.
So you decided to raise an ExitException, and have the caller handle it? I'm asking because the same problem applies to almost every port. Every port has to decide how to handle exits. I wish to come up with some universal solution.
from docopt.php.
Nah, I just closed it because the issue has been sitting around for long enough and the current implementation in PHP allows you to have it both ways - you can let docopt handle the exits or catch them yourself by setting the 'exit' option. I think this is a good enough compromise for now. I'll revisit it if someone raises it and provides a superior alternative, but I haven't had any problems with the current implementation and I've used it hundreds of times now :D
from docopt.php.
Related Issues (10)
- Hangs forever with HHVM HOT 15
- Options section is more rigidly defined than other docopt implementations HOT 3
- Handle quoted multi-word argument & option values HOT 2
- Benefit of static analysis HOT 1
- Readable coding style HOT 1
- No installable candidates for 3 years - how so? HOT 7
- parse_argv doesn't work properly with optionsFirst HOT 2
- Allow args beginning with "-" HOT 8
- How can I represent yes or no value? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from docopt.php.