defmain macro; handles the whole if __name__ == __main__ / main function dance
Example: (defmain [&rest args] (print "now we're having a fun time!") (print args)) Which outputs: $ hy test.hy now we're having a fun time! (['test.hy'],) Includes documentation and tests.
This commit is contained in:
parent
5de39a4e1d
commit
774aad2ca8
@ -441,6 +441,44 @@ symbols for function names as the first parameter, `defn-alias` and
|
||||
=> (alias)
|
||||
"Hello!"
|
||||
|
||||
|
||||
defmain
|
||||
-------
|
||||
|
||||
.. versionadded:: 0.9.13
|
||||
|
||||
The `defmain` macro defines a main function that is immediately called
|
||||
with sys.argv as arguments if and only if this file is being executed
|
||||
as a script. In other words this:
|
||||
|
||||
.. code-block:: clj
|
||||
|
||||
(defmain [&rest args]
|
||||
(do-something-with args))
|
||||
|
||||
is the equivalent of::
|
||||
|
||||
def main(*args):
|
||||
do_something_with(args)
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
retval = main(*sys.arg)
|
||||
|
||||
if isinstance(retval, int):
|
||||
sys.exit(retval)
|
||||
|
||||
Note, as you can see above, if you return an integer from this
|
||||
function, this will be used as the exit status for your script.
|
||||
(Python defaults to exit status 0 otherwise, which means everything's
|
||||
okay!)
|
||||
|
||||
(Since (sys.exit 0) is not run explicitly in case of a non-integer
|
||||
return from defmain, it's good to put (defmain) as the last bit of
|
||||
code in your file.)
|
||||
|
||||
|
||||
.. _defmacro:
|
||||
|
||||
defmacro
|
||||
|
@ -171,6 +171,21 @@
|
||||
(let ~(HyList (map (fn [x] `[~x (gensym (slice '~x 2))]) syms))
|
||||
~@body))))
|
||||
|
||||
|
||||
(defmacro defmain [args &rest body]
|
||||
"Write a function named \"main\" and do the if __main__ dance"
|
||||
(let [[retval (gensym)]]
|
||||
`(do
|
||||
(defn main [~@args]
|
||||
~@body)
|
||||
|
||||
(when (= --name-- "__main__")
|
||||
(import sys)
|
||||
(setv ~retval (apply main sys.argv))
|
||||
(if (integer? ~retval)
|
||||
(sys.exit ~retval))))))
|
||||
|
||||
|
||||
(defmacro-alias [defn-alias defun-alias] [names lambda-list &rest body]
|
||||
"define one function with several names"
|
||||
(let [[main (first names)]
|
||||
|
5
tests/resources/bin/main.hy
Normal file
5
tests/resources/bin/main.hy
Normal file
@ -0,0 +1,5 @@
|
||||
(defmain [&rest args]
|
||||
(print args)
|
||||
(print "Hello World")
|
||||
(if (in "exit1" args)
|
||||
1))
|
4
tests/resources/bin/nomain.hy
Normal file
4
tests/resources/bin/nomain.hy
Normal file
@ -0,0 +1,4 @@
|
||||
(print "This Should Still Works")
|
||||
|
||||
(defn main []
|
||||
(print "This Should Not Work"))
|
@ -142,3 +142,27 @@ def test_bin_hy_builtins():
|
||||
|
||||
assert str(exit) == "Use (exit) or Ctrl-D (i.e. EOF) to exit"
|
||||
assert str(quit) == "Use (quit) or Ctrl-D (i.e. EOF) to exit"
|
||||
|
||||
|
||||
def test_bin_hy_main():
|
||||
ret = run_cmd("hy tests/resources/bin/main.hy")
|
||||
assert ret[0] == 0
|
||||
assert "Hello World" in ret[1]
|
||||
|
||||
|
||||
def test_bin_hy_main_args():
|
||||
ret = run_cmd("hy tests/resources/bin/main.hy test 123")
|
||||
assert ret[0] == 0
|
||||
assert "test" in ret[1]
|
||||
assert "123" in ret[1]
|
||||
|
||||
|
||||
def test_bin_hy_main_exitvalue():
|
||||
ret = run_cmd("hy tests/resources/bin/main.hy exit1")
|
||||
assert ret[0] == 1
|
||||
|
||||
|
||||
def test_bin_hy_no_main():
|
||||
ret = run_cmd("hy tests/resources/bin/nomain.hy")
|
||||
assert ret[0] == 0
|
||||
assert "This Should Still Work" in ret[1]
|
||||
|
Loading…
Reference in New Issue
Block a user