diff --git a/bin/hy b/bin/hy
index 5554f00..1c19538 100755
--- a/bin/hy
+++ b/bin/hy
@@ -1,142 +1,9 @@
#!/usr/bin/env python
-import hy
-
import sys
-import os
+
+from hy.cmdline import cmdline_handler
-if len(sys.argv) > 1:
- from hy.importer import import_file_to_module
- sys.argv.pop(0)
- import_file_to_module("__main__", sys.argv[0])
- sys.exit(0) # right?
-
-
-import readline
-import code
-import ast
-
-from hy.lex.states import Idle, LexException
-from hy.lex.machine import Machine
-from hy.compiler import hy_compile
-from hy.core import process
-from hy.importer import ast_compile
-
-import hy.completer
-
-from hy.macros import macro
-from hy.models.expression import HyExpression
-from hy.models.string import HyString
-from hy.models.symbol import HySymbol
-
-
-_machine = Machine(Idle, 1, 0)
-
-
-class HyREPL(code.InteractiveConsole):
- def runsource(self, source, filename='', symbol='single'):
- global _machine
-
- try:
- _machine.process(source + "\n")
- except LexException as e:
- _machine = Machine(Idle, 1, 0)
- self.showsyntaxerror(filename)
- return False
-
- if type(_machine.state) != Idle:
- _machine = Machine(Idle, 1, 0)
- return True
-
- try:
- tokens = process(_machine.nodes)
- except Exception:
- _machine = Machine(Idle, 1, 0)
- self.showtraceback()
- return False
-
- _machine = Machine(Idle, 1, 0)
- try:
- _ast = hy_compile(tokens, root=ast.Interactive)
- code = ast_compile(_ast, filename, symbol)
- except Exception:
- self.showtraceback()
- return False
-
- self.runcode(code)
- return False
-
-
-sys.ps1 = "=> "
-sys.ps2 = "... "
-
-history = os.path.expanduser("~/.hy-history")
-readline.parse_and_bind("set blink-matching-paren on")
-
-
-@macro("koan")
-def koan_macro(tree):
- return HyExpression([HySymbol('print'),
- HyString("""
- Ummon asked the head monk, "What sutra are you lecturing on?"
- "The Nirvana Sutra."
- "The Nirvana Sutra has the Four Virtues, hasn't it?"
- "It has."
- Ummon asked, picking up a cup, "How many virtues has this?"
- "None at all, " said the monk.
- "But ancient people said it had, didn't they?" said Ummon.
- "Whatdo you think of what they said?"
- Ummon struck the cup and asked, "You understand?"
- "No," said the monk.
- "Then," said Ummon, "You'd better go on with your lectures on the sutra."
-""")])
-
-
-@macro("ideas")
-def koan_macro(tree):
- return HyExpression([HySymbol('print'),
- HyString("""
-
- => (import [sh [figlet]])
- => (figlet "Hi, Hy!")
- _ _ _ _ _ _
- | | | (_) | | | |_ _| |
- | |_| | | | |_| | | | | |
- | _ | |_ | _ | |_| |_|
- |_| |_|_( ) |_| |_|\__, (_)
- |/ |___/
-
-
-;;; string things
-(.join ", " ["what" "the" "heck"])
-
-
-;;; this one plays with command line bits
-(import [sh [cat grep]])
-(-> (cat "/usr/share/dict/words") (grep "-E" "bro$"))
-
-
-;;; filtering a list w/ a lambda
-(filter (lambda [x] (= (% x 2) 0)) (range 0 10))
-
-
-;;; swaggin' functional bits (Python rulez)
-(max (map (lambda [x] (len x)) ["hi" "my" "name" "is" "paul"]))
-
-""")])
-
-
-try:
- readline.read_history_file(history)
-except IOError:
- open(history, 'a').close()
-
-readline.parse_and_bind("tab: complete")
-
-hr = HyREPL()
-hr.interact("{appname} {version}".format(
- appname=hy.__appname__,
- version=hy.__version__
-))
-readline.write_history_file(history)
+if __name__ == '__main__':
+ sys.exit(cmdline_handler("hy", sys.argv))
diff --git a/hy/cmdline.py b/hy/cmdline.py
new file mode 100644
index 0000000..ddc46e9
--- /dev/null
+++ b/hy/cmdline.py
@@ -0,0 +1,194 @@
+import ast
+import code
+import optparse
+import os
+import readline
+import sys
+
+import hy
+
+from hy.lex.states import Idle, LexException
+from hy.lex.machine import Machine
+from hy.compiler import hy_compile
+from hy.core import process
+from hy.importer import ast_compile
+
+import hy.completer
+
+from hy.macros import macro
+from hy.models.expression import HyExpression
+from hy.models.string import HyString
+from hy.models.symbol import HySymbol
+
+
+_machine = Machine(Idle, 1, 0)
+
+
+class HyREPL(code.InteractiveConsole):
+ def runsource(self, source, filename='', symbol='single'):
+ global _machine
+
+ try:
+ _machine.process(source + "\n")
+ except LexException:
+ _machine = Machine(Idle, 1, 0)
+ self.showsyntaxerror(filename)
+ return False
+
+ if type(_machine.state) != Idle:
+ _machine = Machine(Idle, 1, 0)
+ return True
+
+ try:
+ tokens = process(_machine.nodes)
+ except Exception:
+ _machine = Machine(Idle, 1, 0)
+ self.showtraceback()
+ return False
+
+ _machine = Machine(Idle, 1, 0)
+ try:
+ _ast = hy_compile(tokens, root=ast.Interactive)
+ code = ast_compile(_ast, filename, symbol)
+ except Exception:
+ self.showtraceback()
+ return False
+
+ self.runcode(code)
+ return False
+
+
+@macro("koan")
+def koan_macro(tree):
+ return HyExpression([HySymbol('print'),
+ HyString("""
+ Ummon asked the head monk, "What sutra are you lecturing on?"
+ "The Nirvana Sutra."
+ "The Nirvana Sutra has the Four Virtues, hasn't it?"
+ "It has."
+ Ummon asked, picking up a cup, "How many virtues has this?"
+ "None at all, " said the monk.
+ "But ancient people said it had, didn't they?" said Ummon.
+ "Whatdo you think of what they said?"
+ Ummon struck the cup and asked, "You understand?"
+ "No," said the monk.
+ "Then," said Ummon, "You'd better go on with your lectures on the sutra."
+""")])
+
+
+@macro("ideas")
+def ideas_macro(tree):
+ return HyExpression([HySymbol('print'),
+ HyString("""
+
+ => (import [sh [figlet]])
+ => (figlet "Hi, Hy!")
+ _ _ _ _ _ _
+ | | | (_) | | | |_ _| |
+ | |_| | | | |_| | | | | |
+ | _ | |_ | _ | |_| |_|
+ |_| |_|_( ) |_| |_|\__, (_)
+ |/ |___/
+
+
+;;; string things
+(.join ", " ["what" "the" "heck"])
+
+
+;;; this one plays with command line bits
+(import [sh [cat grep]])
+(-> (cat "/usr/share/dict/words") (grep "-E" "bro$"))
+
+
+;;; filtering a list w/ a lambda
+(filter (lambda [x] (= (% x 2) 0)) (range 0 10))
+
+
+;;; swaggin' functional bits (Python rulez)
+(max (map (lambda [x] (len x)) ["hi" "my" "name" "is" "paul"]))
+
+""")])
+
+
+def run_command(source):
+ hr = HyREPL()
+ hr.runsource(source, filename='', symbol='single')
+ return 0
+
+
+def run_file(filename):
+ from hy.importer import import_file_to_module
+ import_file_to_module("__main__", filename)
+ return 0 # right?
+
+
+def run_repl(hr=None):
+ sys.ps1 = "=> "
+ sys.ps2 = "... "
+
+ history = os.path.expanduser("~/.hy-history")
+ readline.parse_and_bind("set blink-matching-paren on")
+
+ try:
+ readline.read_history_file(history)
+ except IOError:
+ open(history, 'a').close()
+
+ readline.parse_and_bind("tab: complete")
+
+ if not hr:
+ hr = HyREPL()
+ hr.interact("{appname} {version}".format(
+ appname=hy.__appname__,
+ version=hy.__version__
+ ))
+ readline.write_history_file(history)
+ return 0
+
+
+def run_icommand(source):
+ hr = HyREPL()
+ hr.runsource(source, filename='', symbol='single')
+ return run_repl(hr)
+
+
+USAGE = "usage: %prog [-h | -i cmd | -c cmd | file | -]"
+VERSION = "%prog " + hy.__version__
+EPILOG = """ file program read from script
+ - program read from stdin
+"""
+
+
+def cmdline_handler(scriptname, argv):
+ parser = optparse.OptionParser(usage=USAGE, version=VERSION)
+ parser.add_option(
+ "-c", dest="command", metavar="COMMAND",
+ help="program passed in as string")
+ parser.add_option(
+ "-i", dest="icommand", metavar="ICOMMAND",
+ help="program passed in as string, then stay in repl")
+
+ # Hylarious way of adding non-option options to help text
+ parser.format_epilog = lambda self: EPILOG
+
+ (options, args) = parser.parse_args()
+
+ if options.command:
+ # User did "hy -c ..."
+ return run_command(options.command)
+
+ if options.icommand:
+ # User did "hy -i ..."
+ return run_icommand(options.icommand)
+
+ if args:
+ if args[0] == "-":
+ # Read the program from stdin
+ return run_command(sys.stdin.read())
+
+ else:
+ # User did "hy "
+ return run_file(args[0])
+
+ # User did NOTHING!
+ return run_repl()