commandBuiltin :: [String] -> Shell ExitCode
commandBuiltin = run `flip` Empty
    where run [] _ = return ExitSuccess
          run (('-':a:[]):as) m = run as $ mode m a
          run (('-':a:a'):as) m = run (('-':a'):as) $ mode m a
          run (s:args) Empty = do rs <- resolveCommand s
                                  case take 1 rs of
                                    [Executable fp] -> runInShell fp args
                                    [Builtin b] -> b args
                                    _ -> failWith 127 $ s++": command not found"
          run (s:args) Path = run (s:args) Empty -- for now...?
          run ss Basic = anyM ss $ \s -> short s =<< resolveCommand s
          run ss Verb = anyM ss $ \s -> doType "command" s =<< resolveCommand s
          mode m c = case c of { 'p'->Path; 'v'->Basic; 'V'->Verb; _->m }
          anyM ss f = do res <- forM ss f
                         if any id res then return ExitSuccess
                                       else return $ ExitFailure 1
          short s (x:_:_) = short s [x]
          short _ [Executable fp] = oPutStrLn fp >> return True
          short s [Builtin _] = oPutStrLn s >> return True
          short s [Keyword] = oPutStrLn s >> return True
          short s [Function _ _] = oPutStrLn s >> return True
          short s [Alias s'] = showAlias s s' >> return True
          short _ [] = return False
commandBuiltin :: [String] -> Shell ExitCode
commandBuiltin = run `flip` Empty
    where run [] _ = return ExitSuccess
          run (('-':a:[]):as) m = run as $ mode m a
          run (('-':a:a'):as) m = run (('-':a'):as) $ mode m a
          run (s:args) Empty = do rs <- resolveCommand s
                                  case take 1 rs of
                                    [Executable fp] -> runInShell fp args
                                    [Builtin b] -> b args
                                    _ -> failWith 127 $ s++": command not found"
          run (s:args) Path = run (s:args) Empty -- for now...?
          run ss Basic = anyM ss $ \s -> short s =<< resolveCommand s
          run ss Verb = anyM ss $ \s -> doType "command" s =<< resolveCommand s
          mode m c = case c of { 'p'->Path; 'v'->Basic; 'V'->Verb; _->m }
          anyM ss f = do res <- forM ss f
                         if any id res then return ExitSuccess
                                       else return $ ExitFailure 1
          short s (x:_:_) = short s [x]
          short _ [Executable fp] = oPutStrLn fp >> return True
          short s [Builtin _] = oPutStrLn s >> return True
          short s [Keyword] = oPutStrLn s >> return True
          short s [Function _ _] = oPutStrLn s >> return True
          short s [Alias s'] = showAlias s s' >> return True
          short _ [] = return False
commandBuiltin = run `flip` Empty
    where run [] _ = return ExitSuccess
          run (('-':a:[]):as) m = run as $ mode m a
          run (('-':a:a'):as) m = run (('-':a'):as) $ mode m a
          run (s:args) Empty = do rs <- resolveCommand s
                                  case take 1 rs of
                                    [Executable fp] -> runInShell fp args
                                    [Builtin b] -> b args
                                    _ -> failWith 127 $ s++": command not found"
          run (s:args) Path = run (s:args) Empty -- for now...?
          run ss Basic = anyM ss $ \s -> short s =<< resolveCommand s
          run ss Verb = anyM ss $ \s -> doType "command" s =<< resolveCommand s
          mode m c = case c of { 'p'->Path; 'v'->Basic; 'V'->Verb; _->m }
          anyM ss f = do res <- forM ss f
                         if any id res then return ExitSuccess
                                       else return $ ExitFailure 1
          short s (x:_:_) = short s [x]
          short _ [Executable fp] = oPutStrLn fp >> return True
          short s [Builtin _] = oPutStrLn s >> return True
          short s [Keyword] = oPutStrLn s >> return True
          short s [Function _ _] = oPutStrLn s >> return True
          short s [Alias s'] = showAlias s s' >> return True
          short _ [] = return False