summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--doc/guix.texi51
-rw-r--r--guix/scripts/repl.scm77
-rw-r--r--tests/guix-repl.sh84
4 files changed, 179 insertions, 34 deletions
diff --git a/Makefile.am b/Makefile.am
index 9cf9318e8a9..8988cdfa127 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -477,6 +477,7 @@ SH_TESTS = \
477 tests/guix-environment-container.sh \ 477 tests/guix-environment-container.sh \
478 tests/guix-graph.sh \ 478 tests/guix-graph.sh \
479 tests/guix-describe.sh \ 479 tests/guix-describe.sh \
480 tests/guix-repl.sh \
480 tests/guix-lint.sh 481 tests/guix-lint.sh
481 482
482TESTS = $(SCM_TESTS) $(SH_TESTS) 483TESTS = $(SCM_TESTS) $(SH_TESTS)
diff --git a/doc/guix.texi b/doc/guix.texi
index 510347b2222..d55eaff02c5 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -239,7 +239,7 @@ Programming Interface
239* Derivations:: Low-level interface to package derivations. 239* Derivations:: Low-level interface to package derivations.
240* The Store Monad:: Purely functional interface to the store. 240* The Store Monad:: Purely functional interface to the store.
241* G-Expressions:: Manipulating build expressions. 241* G-Expressions:: Manipulating build expressions.
242* Invoking guix repl:: Fiddling with Guix interactively. 242* Invoking guix repl:: Programming Guix in Guile
243 243
244Defining Packages 244Defining Packages
245 245
@@ -5474,7 +5474,7 @@ package definitions.
5474* Derivations:: Low-level interface to package derivations. 5474* Derivations:: Low-level interface to package derivations.
5475* The Store Monad:: Purely functional interface to the store. 5475* The Store Monad:: Purely functional interface to the store.
5476* G-Expressions:: Manipulating build expressions. 5476* G-Expressions:: Manipulating build expressions.
5477* Invoking guix repl:: Fiddling with Guix interactively. 5477* Invoking guix repl:: Programming Guix in Guile
5478@end menu 5478@end menu
5479 5479
5480@node Package Modules 5480@node Package Modules
@@ -8248,12 +8248,47 @@ has an associated gexp compiler, such as a @code{<package>}.
8248@node Invoking guix repl 8248@node Invoking guix repl
8249@section Invoking @command{guix repl} 8249@section Invoking @command{guix repl}
8250 8250
8251@cindex REPL, read-eval-print loop 8251@cindex REPL, read-eval-print loop, script
8252The @command{guix repl} command spawns a Guile @dfn{read-eval-print loop} 8252The @command{guix repl} command makes it easier to program Guix in Guile
8253(REPL) for interactive programming (@pxref{Using Guile Interactively,,, guile, 8253by launching a Guile @dfn{read-eval-print loop} (REPL) for interactive
8254GNU Guile Reference Manual}). Compared to just launching the @command{guile} 8254programming (@pxref{Using Guile Interactively,,, guile,
8255GNU Guile Reference Manual}), or by running Guile scripts
8256(@pxref{Running Guile Scripts,,, guile,
8257GNU Guile Reference Manual}).
8258Compared to just launching the @command{guile}
8255command, @command{guix repl} guarantees that all the Guix modules and all its 8259command, @command{guix repl} guarantees that all the Guix modules and all its
8256dependencies are available in the search path. You can use it this way: 8260dependencies are available in the search path.
8261
8262The general syntax is:
8263
8264@example
8265guix repl @var{options} [@var{file} @var{args}]
8266@end example
8267
8268When a @var{file} argument is provided, @var{file} is
8269executed as a Guile scripts:
8270
8271@example
8272guix repl my-script.scm
8273@end example
8274
8275To pass arguments to the script, use @code{--} to prevent them from
8276being interpreted as arguments to @command{guix repl} itself:
8277
8278@example
8279guix repl -- my-script.scm --input=foo.txt
8280@end example
8281
8282To make a script executable directly from the shell, using the guix
8283executable that is on the user's search path, add the following two
8284lines at the top of the script:
8285
8286@example
8287@code{#!/usr/bin/env -S guix repl --}
8288@code{!#}
8289@end example
8290
8291Without a file name argument, a Guile REPL is started:
8257 8292
8258@example 8293@example
8259$ guix repl 8294$ guix repl
@@ -8302,7 +8337,7 @@ Add @var{directory} to the front of the package module search path
8302(@pxref{Package Modules}). 8337(@pxref{Package Modules}).
8303 8338
8304This allows users to define their own packages and make them visible to 8339This allows users to define their own packages and make them visible to
8305the command-line tool. 8340the script or REPL.
8306 8341
8307@item -q 8342@item -q
8308Inhibit loading of the @file{~/.guile} file. By default, that 8343Inhibit loading of the @file{~/.guile} file. By default, that
diff --git a/guix/scripts/repl.scm b/guix/scripts/repl.scm
index ff1f2088940..e2679f4301d 100644
--- a/guix/scripts/repl.scm
+++ b/guix/scripts/repl.scm
@@ -1,6 +1,7 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com> 3;;; Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
4;;; Copyright © 2020 Konrad Hinsen <konrad.hinsen@fastmail.net>
4;;; 5;;;
5;;; This file is part of GNU Guix. 6;;; This file is part of GNU Guix.
6;;; 7;;;
@@ -22,6 +23,7 @@
22 #:use-module (guix scripts) 23 #:use-module (guix scripts)
23 #:use-module (guix repl) 24 #:use-module (guix repl)
24 #:use-module (srfi srfi-1) 25 #:use-module (srfi srfi-1)
26 #:use-module (srfi srfi-26)
25 #:use-module (srfi srfi-37) 27 #:use-module (srfi srfi-37)
26 #:use-module (ice-9 match) 28 #:use-module (ice-9 match)
27 #:use-module (rnrs bytevectors) 29 #:use-module (rnrs bytevectors)
@@ -32,7 +34,8 @@
32 34
33;;; Commentary: 35;;; Commentary:
34;;; 36;;;
35;;; This command provides a Guile REPL 37;;; This command provides a Guile script runner and REPL in an environment
38;;; that contains all the modules comprising Guix.
36 39
37(define %default-options 40(define %default-options
38 `((type . guile))) 41 `((type . guile)))
@@ -63,8 +66,9 @@
63 66
64 67
65(define (show-help) 68(define (show-help)
66 (display (G_ "Usage: guix repl [OPTIONS...] 69 (display (G_ "Usage: guix repl [OPTIONS...] [-- FILE ARGS...]
67Start a Guile REPL in the Guix execution environment.\n")) 70In the Guix execution environment, run FILE as a Guile script with
71command-line arguments ARGS. If no FILE is given, start a Guile REPL.\n"))
68 (display (G_ " 72 (display (G_ "
69 -t, --type=TYPE start a REPL of the given TYPE")) 73 -t, --type=TYPE start a REPL of the given TYPE"))
70 (display (G_ " 74 (display (G_ "
@@ -135,12 +139,13 @@ call THUNK."
135 139
136(define (guix-repl . args) 140(define (guix-repl . args)
137 (define opts 141 (define opts
138 ;; Return the list of package names.
139 (args-fold* args %options 142 (args-fold* args %options
140 (lambda (opt name arg result) 143 (lambda (opt name arg result)
141 (leave (G_ "~A: unrecognized option~%") name)) 144 (leave (G_ "~A: unrecognized option~%") name))
142 (lambda (arg result) 145 (lambda (arg result)
143 (leave (G_ "~A: extraneous argument~%") arg)) 146 (append `((script . ,arg)
147 (ignore-dot-guile . #t))
148 result))
144 %default-options)) 149 %default-options))
145 150
146 (define user-config 151 (define user-config
@@ -148,28 +153,48 @@ call THUNK."
148 (lambda (home) 153 (lambda (home)
149 (string-append home "/.guile")))) 154 (string-append home "/.guile"))))
150 155
156 (define (set-user-module)
157 (set-current-module user-module)
158 (when (and (not (assoc-ref opts 'ignore-dot-guile?))
159 user-config
160 (file-exists? user-config))
161 (load user-config)))
162
163 (define script
164 (reverse
165 (filter-map (match-lambda
166 (('script . script) script)
167 (_ #f))
168 opts)))
169
151 (with-error-handling 170 (with-error-handling
152 (let ((type (assoc-ref opts 'type))) 171
153 (call-with-connection (assoc-ref opts 'listen) 172 (unless (null? script)
154 (lambda () 173 ;; Run script
155 (case type 174 (save-module-excursion
156 ((guile) 175 (lambda ()
157 (save-module-excursion 176 (set-program-arguments script)
158 (lambda () 177 (set-user-module)
159 (set-current-module user-module) 178 (load-in-vicinity "." (car script)))))
160 (when (and (not (assoc-ref opts 'ignore-dot-guile?)) 179
161 user-config 180 (when (null? script)
162 (file-exists? user-config)) 181 ;; Start REPL
163 (load user-config)) 182 (let ((type (assoc-ref opts 'type)))
164 183 (call-with-connection (assoc-ref opts 'listen)
165 ;; Do not exit repl on SIGINT. 184 (lambda ()
166 ((@@ (ice-9 top-repl) call-with-sigint) 185 (case type
167 (lambda () 186 ((guile)
168 (start-repl)))))) 187 (save-module-excursion
169 ((machine) 188 (lambda ()
170 (machine-repl)) 189 (set-user-module)
171 (else 190 ;; Do not exit repl on SIGINT.
172 (leave (G_ "~a: unknown type of REPL~%") type)))))))) 191 ((@@ (ice-9 top-repl) call-with-sigint)
192 (lambda ()
193 (start-repl))))))
194 ((machine)
195 (machine-repl))
196 (else
197 (leave (G_ "~a: unknown type of REPL~%") type)))))))))
173 198
174;; Local Variables: 199;; Local Variables:
175;; eval: (put 'call-with-connection 'scheme-indent-function 1) 200;; eval: (put 'call-with-connection 'scheme-indent-function 1)
diff --git a/tests/guix-repl.sh b/tests/guix-repl.sh
new file mode 100644
index 00000000000..e1c2b8241fe
--- /dev/null
+++ b/tests/guix-repl.sh
@@ -0,0 +1,84 @@
1# GNU Guix --- Functional package management for GNU
2# Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
3# Copyright © 2020 Konrad Hinsen <konrad.hinsen@fastmail.net>
4#
5# This file is part of GNU Guix.
6#
7# GNU Guix is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or (at
10# your option) any later version.
11#
12# GNU Guix is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
20#
21# Test the `guix repl' command-line utility.
22#
23
24guix repl --version
25
26test_directory="`mktemp -d`"
27export test_directory
28trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT
29
30tmpfile="$test_directory/foo.scm"
31rm -f "$tmpfile"
32trap 'rm -f "$tmpfile"' EXIT
33
34module_dir="t-guix-repl-$$"
35mkdir "$module_dir"
36trap 'rm -rf "$module_dir"' EXIT
37
38
39cat > "$tmpfile"<<EOF
40(use-modules (guix packages)
41 (gnu packages base))
42
43(format #t "~a\n" (package-name coreutils))
44EOF
45
46test "`guix repl "$tmpfile"`" = "coreutils"
47
48
49cat > "$module_dir/foo.scm"<<EOF
50(define-module (foo)
51 #:use-module (guix packages)
52 #:use-module (gnu packages base))
53
54(define-public dummy
55 (package (inherit hello)
56 (name "dummy")
57 (version "42")
58 (synopsis "dummy package")
59 (description "dummy package. Only used for testing purposes.")))
60EOF
61
62cat > "$tmpfile"<<EOF
63(use-modules (guix packages)
64 (foo))
65
66(format #t "~a\n" (package-version dummy))
67EOF
68
69test "`guix repl "$tmpfile" -L "$module_dir"`" = "42"
70
71cat > "$tmpfile"<<EOF
72(format #t "~a\n" (cdr (command-line)))
73EOF
74
75test "`guix repl -- "$tmpfile" -a b --input=foo.txt`" = "(-a b --input=foo.txt)"
76
77cat > "$tmpfile"<<EOF
78#!$(type -P env) -S guix repl --
79!#
80(format #t "~a\n" (cdr (command-line)))
81EOF
82chmod 755 $tmpfile
83
84test "`"$tmpfile" -a b --input=foo.txt`" = "(-a b --input=foo.txt)"