;;; Gash --- Guile As SHell
;;; Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of Gash.
;;;
;;; Gash is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Gash is distributed in the hope that it will be useful, but WITHOUT ANY
;;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
;;; details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Gash.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gash built-ins command)
  #:use-module (ice-9 getopt-long)
  #:use-module (gash config)
  #:use-module (gash built-ins))

;;; Commentary:
;;;
;;; The 'command' utility.
;;;
;;; Code:

(define (built-in? name)
  (or (search-special-built-ins name)
      (search-built-ins name)))

(define (PATH-search-path program)
  (search-path (string-split (getenv "PATH") #\:) program))

(define main
  (case-lambda
    (() #t)
    (args
     (let* ((option-spec
             '((describe (single-char #\V))
               (help)
               (show (single-char #\v))
               (version)))
            (options (getopt-long (cons "command" args) option-spec
                                  #:stop-at-first-non-option #t))
            (help? (option-ref options 'help #f))
            (version? (option-ref options 'version #f))
            (files (option-ref options '() '())))
       (cond (help? (display "Usage: command [OPTION]... [COMMAND [ARG]...]

Options:
  --help     display this help and exit
  --version  display version information and exit
  -v         display a description of COMMAND similar to the `type' builtin
  -V         display a more verbose description of COMMAND
"))
             (version? (format #t "command (GASH) ~a\n" %version))
             ((null? files) #t)
             ((option-ref options 'describe #f)
              (let ((command (car files)))
                (cond ((built-in? command)
                       (format #t "~a is a shell builtin\n" command)
                       EXIT_SUCCESS)
                      ((PATH-search-path command)
                       =>
                       (lambda (program)
                         (format #t "~a hashed (~a)\n" command program)
                         EXIT_SUCCESS))
                      (else EXIT_FAILURE))))
             ((option-ref options 'show #f)
              (let ((command (car files)))
                (cond ((built-in? command)
                       (display command)
                       EXIT_SUCCESS)
                      ((PATH-search-path command)
                       =>
                       (lambda (program)
                         (format #t "~a\n" program)
                         EXIT_SUCCESS))
                      (else EXIT_FAILURE))))
             (else (let* ((command (car files))
                          (built-in? command))
                     ((@@ (gash built-ins eval) main) (string-join args)))))))))
