Add support for built-ins, starting with 'echo'

* geesh/built-ins/echo.scm: New file.
* geesh/built-ins.scm: New file.
* Makefile.scm: Add them.
* geesh/shell.scm (exec-let): Include built-ins in command search.
* tests/shell.scm: Add a test for this.
This commit is contained in:
Timothy Sample 2018-07-17 11:20:06 -04:00
parent 7cc94e88e1
commit e1f139b841
5 changed files with 133 additions and 1 deletions

View File

@ -37,6 +37,8 @@ endif # HAVE_GENHTML
test-list: ; @echo $(TESTS)
MODULES = \
geesh/built-ins/echo.scm \
geesh/built-ins.scm \
geesh/environment.scm \
geesh/lexer.scm \
geesh/parser.scm \

80
geesh/built-ins.scm Normal file
View File

@ -0,0 +1,80 @@
;;; The Geesh Shell Interpreter
;;; Copyright 2018 Timothy Sample <samplet@ngyro.com>
;;;
;;; This file is part of Geesh.
;;;
;;; Geesh 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.
;;;
;;; Geesh 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 Geesh. If not, see <http://www.gnu.org/licenses/>.
(define-module (geesh built-ins)
#:use-module (geesh built-ins echo)
#:export (search-built-ins
search-special-built-ins))
;;; Commentary:
;;;
;;; This module provides built-in searching functions.
;;;
;;; Code:
(define (undefined env . args)
(throw 'undefined-built-in))
;; Special built-ins take precedence over any other command.
(define *special-built-ins*
`(("." . ,undefined)
(":" . ,undefined)
("break" . ,undefined)
("continue" . ,undefined)
("eval" . ,undefined)
("exec" . ,undefined)
("exit" . ,undefined)
("export" . ,undefined)
("readonly" . ,undefined)
("return" . ,undefined)
("set" . ,undefined)
("shift" . ,undefined)
("times" . ,undefined)
("trap" . ,undefined)
("unset" . ,undefined)))
;; Regular built-ins take precendence over utilities in the search
;; path, but not over functions.
(define *built-ins*
`( ;; POSIX-specified built-ins.
("alias" . ,undefined)
("bg" . ,undefined)
("cd" . ,undefined)
("command" . ,undefined)
("false" . ,undefined)
("fc" . ,undefined)
("fg" . ,undefined)
("getopts" . ,undefined)
("hash" . ,undefined)
("jobs" . ,undefined)
("kill" . ,undefined)
("newgrp" . ,undefined)
("pwd" . ,undefined)
("read" . ,undefined)
("true" . ,undefined)
("umask" . ,undefined)
("unalias" . ,undefined)
("wait" . ,undefined)
;; Other built-ins.
("echo" . ,echo)))
(define (search-special-built-ins name)
(assoc-ref *special-built-ins* name))
(define (search-built-ins name)
(assoc-ref *built-ins* name))

30
geesh/built-ins/echo.scm Normal file
View File

@ -0,0 +1,30 @@
;;; The Geesh Shell Interpreter
;;; Copyright 2018 Timothy Sample <samplet@ngyro.com>
;;;
;;; This file is part of Geesh.
;;;
;;; Geesh 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.
;;;
;;; Geesh 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 Geesh. If not, see <http://www.gnu.org/licenses/>.
(define-module (geesh built-ins echo)
#:export (echo))
;;; Commentary:
;;;
;;; The 'echo' utility.
;;;
;;; Code:
(define (echo env . args)
(display (string-join args " "))
(newline))

View File

@ -1,4 +1,5 @@
(define-module (geesh shell)
#:use-module (geesh built-ins)
#:use-module (geesh environment)
#:use-module (ice-9 match)
#:export (sh:exec-let
@ -47,7 +48,19 @@ it cannot be found, return @code{#f}."
"Find and execute @var{name} with arguments @var{args}, environment
@var{env}, and extra environment variable bindings @var{bindings}."
(if (slashless? name)
(or (and=> (find-utility env name)
(or (and=> (search-special-built-ins name)
(lambda (proc)
(for-each (match-lambda
((name . value)
(set-var! env name value)))
bindings)
(apply proc env args)))
;; TODO: Functions.
(and=> (search-built-ins name)
(lambda (proc)
;; TODO: Use 'bindings' here.
(apply proc env args)))
(and=> (find-utility env name)
(lambda (path)
(exec-utility env bindings path name args)))
(error "Command not found."))

View File

@ -120,4 +120,11 @@
(('misc-error _ _ ("Command not found.") _) #t)
(_ #f))))))))
(test-equal "Executes regular built-ins"
"foo bar\n"
(let ((env (make-environment '())))
(with-output-to-string
(lambda ()
(sh:exec env "echo" "foo" "bar")))))
(test-end)