update coverage, add tests for arg parsing and fix arg parsing
diff --git a/typ/__main__.py b/typ/__main__.py
index 1e97876..157ab50 100644
--- a/typ/__main__.py
+++ b/typ/__main__.py
@@ -18,7 +18,7 @@
 
 
 if __name__ == '__main__':
-    if sys.platform == 'win32':
+    if sys.platform == 'win32': # pragma: no cover
         sys.exit(main.spawn_main())
     else:
         sys.exit(main.main())
diff --git a/typ/arg_parser.py b/typ/arg_parser.py
index aecd4a4..002525d 100644
--- a/typ/arg_parser.py
+++ b/typ/arg_parser.py
@@ -14,12 +14,22 @@
 
 import argparse
 
+from typ.host import Host
+
+
+class _Bailout(Exception):
+    pass
+
 
 class ArgumentParser(argparse.ArgumentParser):
     def __init__(self, *args, **kwargs):
+        self._host = kwargs['host']
+        del kwargs['host']
         super(ArgumentParser, self).__init__(*args, **kwargs)
+
         self.exit_status = None
         self.exit_message = None
+
         self.usage = '%(prog)s [options] [tests...]'
         self.add_argument('--builder-name',
                           help=('Builder name to include in the '
@@ -98,6 +108,27 @@
         self.add_argument('tests', nargs='*', default=[],
                           help=argparse.SUPPRESS)
 
+    def parse_args(self, args=None, namespace=None):
+        try:
+            super(ArgumentParser, self).parse_args(args=args,
+                                                   namespace=namespace)
+        except _Bailout:
+            pass
+
+    def _print_message(self, msg, file=None):
+        self._host.print_(msg=msg, stream=file, end='')
+
+    def print_usage(self, file=None):
+        self._print_message(self.format_usage(), file=file)
+
+    def print_help(self, file=None):
+        self._print_message(msg=self.format_help(), file=file)
+
+    def error(self, message):
+        self.exit(2, '%s: error: %s\n' % (self.prog, message))
+
     def exit(self, status=0, message=None):
         self.exit_status = status
-        self.exit_message = message
+        if message:
+            self._print_message(message, file=self._host.stderr)
+        raise _Bailout()
diff --git a/typ/runner.py b/typ/runner.py
index fe470f6..b1a65d6 100644
--- a/typ/runner.py
+++ b/typ/runner.py
@@ -75,12 +75,10 @@
         self._cov = None
 
     def main(self, argv=None):
-        parser = ArgumentParser()
-        exit_status, exit_message = self.parse_args(parser, argv)
-        if exit_status is not None:
-            if exit_status:
-                self.print_(exit_message, stream=self.host.stderr)
-            return exit_status
+        parser = ArgumentParser(host=self.host)
+        self.parse_args(parser, argv)
+        if parser.exit_status is not None:
+            return parser.exit_status
 
         try:
             ret, full_results = self.run()
@@ -103,7 +101,6 @@
 
         # TODO: Decide if this is sufficiently idiot-proof.
         parser.parse_args(args=args, namespace=self)
-        return parser.exit_status, parser.exit_message
 
     def print_(self, msg='', end='\n', stream=None):
         self.host.print_(msg, end, stream=stream)
@@ -148,17 +145,17 @@
                             'with --test-result-server')
                 ret = 2
 
-        if self.debugger:
+        if self.debugger: # pragma: no cover
             self.jobs = 1
             self.passthrough = True
 
-        if self.coverage:
+        if self.coverage: # pragma: no cover
             self.jobs = 1
 
         self.stats = Stats(self.status_format, h.time, self.jobs)
 
-        should_overwrite = h.stdout.isatty() and not self.verbose
-        self.printer = Printer(self.print_, should_overwrite,
+        self.should_overwrite = h.stdout.isatty() and not self.verbose
+        self.printer = Printer(self.print_, self.should_overwrite,
                                cols=self.terminal_width)
 
         if not self.top_level_dir:
@@ -172,7 +169,7 @@
         for path in self.path:
             h.add_to_path(path)
 
-        if self.coverage:
+        if self.coverage: # pragma: no cover
             self._cov = coverage.coverage()
 
         return ret
@@ -392,11 +389,11 @@
                      '' if num_failures == 1 else 's'))
         self.print_()
 
-    def write_results(self, full_results):
+    def write_results(self, full_results): # pragma: no cover
         if self.write_full_results_to:
             self.host.write_text_file(json.dumps(full_results, indent=2) + '\n')
 
-    def upload_results(self, full_results):
+    def upload_results(self, full_results): # pragma: no cover
         h = self.host
         if not self.test_results_server:
             return 0
@@ -415,10 +412,10 @@
         return 1
 
     def report_coverage(self):
-        if self._cov:
+        if self._cov: # pragma: no cover
             self._cov.report(show_missing=False, omit=self.coverage_omit)
 
-    def exit_code_from_full_results(self, full_results):
+    def exit_code_from_full_results(self, full_results): # pragma: no cover
         return json_results.exit_code_from_full_results(full_results)
 
 
@@ -495,13 +492,13 @@
         self.stream = stream
         super(PassThrough, self).__init__()
 
-    def write(self, msg, *args, **kwargs):
-        if self.stream: # pragma: no cover
+    def write(self, msg, *args, **kwargs): # pragma: no cover
+        if self.stream:
             self.stream.write(unicode(msg), *args, **kwargs)
         super(PassThrough, self).write(unicode(msg), *args, **kwargs)
 
-    def flush(self, *args, **kwargs):
-        if self.stream: # pragma: no cover
+    def flush(self, *args, **kwargs): # pragma: no cover
+        if self.stream:
             self.stream.flush(*args, **kwargs)
         super(PassThrough, self).flush(*args, **kwargs)
 
diff --git a/typ/tests/main_test.py b/typ/tests/main_test.py
index bb648cb..3110f3d 100644
--- a/typ/tests/main_test.py
+++ b/typ/tests/main_test.py
@@ -61,6 +61,10 @@
 class TestCli(test_case.MainTestCase):
     prog = [sys.executable, '-m', 'typ']
 
+    def test_bad_arg(self):
+        self.check(['--bad-arg'], ret=2)
+        self.check(['-help'], ret=2)
+
     def test_bad_metadata(self):
         self.check(['--metadata', 'foo'], ret=2)