From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id kKo3KYon214tCwAA0tVLHw (envelope-from ) for ; Sat, 06 Jun 2020 05:20:10 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id CHcBJYon217GDgAA1q6Kng (envelope-from ) for ; Sat, 06 Jun 2020 05:20:10 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 8EC35940391 for ; Sat, 6 Jun 2020 05:20:09 +0000 (UTC) Received: from localhost ([::1]:39678 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jhRFY-00019Q-DS for larch@yhetil.org; Sat, 06 Jun 2020 01:20:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34972) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jhRFS-00019I-7n for guix-patches@gnu.org; Sat, 06 Jun 2020 01:20:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:38941) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jhRFR-0007ku-UN for guix-patches@gnu.org; Sat, 06 Jun 2020 01:20:01 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1jhRFR-0001ju-PL for guix-patches@gnu.org; Sat, 06 Jun 2020 01:20:01 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#41253] [PATCH v4] guix repl: Add script execution. Resent-From: Konrad Hinsen Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 06 Jun 2020 05:20:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 41253 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 41253@debbugs.gnu.org Received: via spool by 41253-submit@debbugs.gnu.org id=B41253.15914207646628 (code B ref 41253); Sat, 06 Jun 2020 05:20:01 +0000 Received: (at 41253) by debbugs.gnu.org; 6 Jun 2020 05:19:24 +0000 Received: from localhost ([127.0.0.1]:50487 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jhREb-0001iV-Lj for submit@debbugs.gnu.org; Sat, 06 Jun 2020 01:19:23 -0400 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:35519) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jhREY-0001i4-PR for 41253@debbugs.gnu.org; Sat, 06 Jun 2020 01:19:08 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id DDA4E4E6; Sat, 6 Jun 2020 01:19:00 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Sat, 06 Jun 2020 01:19:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fastmail.net; h= from:to:subject:in-reply-to:references:date:message-id :mime-version:content-type:content-transfer-encoding; s=fm3; bh= 2S+1HihZU1RBuTuk6JNEYFhaPdw+yrnGzzfJosbQMMU=; b=wRZjsY7gtawXdexq yFLog/pHILUmqaCogQZNTLOWcCTMWgrT8Z1r5LbjU3+2z0e1lUboqtaPv45i/7Qa IbQZyof9OsWXsloJ1c1mr/d39g7c5A9MBG7RQmTzkGX0K4BCbNBR4a9FXYYZCMDO HRSksQI6xnWAt71MbnAPlKT8MJOXRU/MrKCfuncSRNKPtGraDKNGPd/B2q4D3iJp qAmka0KQzBEruRc1Ublp86LVMo7wGYZdsQOK3lkVlB5Bta+fVIkKphQyrmN8OWjV gSo8HVMqnQsAxw8jLj4qKZkwohJof1BZnbS1ZkoqWemOYngEtRLjFN5Lz56D0YiF CKMwzw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; bh=2S+1HihZU1RBuTuk6JNEYFhaPdw+yrnGzzfJosbQM MU=; b=H91iQxfVH7ECAZS14/sxoOv+URo9fq5glcYbNC3Etnmt6aHrd3BvrDF3N fhd5/zu/I/4BUnCU4MozI+O7PV2KHtvv8SPo8wxId/Y9YWctmRcq4wMxv+N1J3oc l9Nncgz9RRNMtYYwV4kJ1+e8GPYyWbyBdlSYTuAvKN8EEz6u4xBzW/7WBM4tq390 akTMBGgOyfsmVQ/EQX+BXqX1eQEzDGKjcWKuDcb5KygQTZQjMmggMahON1qkje+t wKMf3Ow9+xLwgCpI01rsowM5F077MRNHakepz8Nw1nW2wGlzRBcW3pvh/hQGp44l HRygFUdRbOyOUas5xi7fp/V7UDDrg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduhedrudeggedgkeejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffujghffffkgggtgfesthhqre dttddtjeenucfhrhhomhepmfhonhhrrgguucfjihhnshgvnhcuoehkohhnrhgrugdrhhhi nhhsvghnsehfrghsthhmrghilhdrnhgvtheqnecuggftrfgrthhtvghrnhepgeefhfefke ehtdekuddtffdtledtveffffeihfekgfekfeffleefveekheegheeinecuffhomhgrihhn pehgnhhurdhorhhgnecukfhppeelvddrudeiledrudejfedrvddvheenucevlhhushhtvg hrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehkohhnrhgrugdrhhhinhhs vghnsehfrghsthhmrghilhdrnhgvth X-ME-Proxy: Received: from khs-macbook.home (lfbn-idf2-1-1364-225.w92-169.abo.wanadoo.fr [92.169.173.225]) by mail.messagingengine.com (Postfix) with ESMTPA id 893313280065; Sat, 6 Jun 2020 01:18:59 -0400 (EDT) From: Konrad Hinsen In-Reply-To: References: <20200514162537.29071-1-zimon.toutoune@gmail.com> Date: Sat, 06 Jun 2020 07:18:58 +0200 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Spam-Score: -1.0 (-) X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Scanner: scn0 Authentication-Results: aspmx1.migadu.com; dkim=fail (body hash did not verify) header.d=fastmail.net header.s=fm3 header.b=wRZjsY7g; dkim=fail (body hash did not verify) header.d=messagingengine.com header.s=fm3 header.b=H91iQxfV; dmarc=fail reason="SPF not aligned (relaxed)" header.from=fastmail.net (policy=none); spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Spam-Score: 0.09 X-TUID: 1UnpUcKUT1/L * guix/scripts/repl.scm: Add filename options for script execution. * doc/guix.texi (Invoking guix repl): Document it. * tests/guix-repl.sh: Test it. * Makefile.am: (SH_TESTS): Add it. --- Makefile.am | 1 + doc/guix.texi | 51 +++++++++++++++++++++----- guix/scripts/repl.scm | 82 ++++++++++++++++++++++++++++-------------- tests/guix-repl.sh | 84 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+), 34 deletions(-) create mode 100644 tests/guix-repl.sh diff --git a/Makefile.am b/Makefile.am index 5b64386b53..859b6a4bc2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -473,6 +473,7 @@ SH_TESTS =3D \ tests/guix-environment-container.sh \ tests/guix-graph.sh \ tests/guix-describe.sh \ + tests/guix-repl.sh \ tests/guix-lint.sh =20 TESTS =3D $(SCM_TESTS) $(SH_TESTS) diff --git a/doc/guix.texi b/doc/guix.texi index 056bf011f6..b95709d0c6 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -239,7 +239,7 @@ Programming Interface * Derivations:: Low-level interface to package derivations. * The Store Monad:: Purely functional interface to the store. * G-Expressions:: Manipulating build expressions. -* Invoking guix repl:: Fiddling with Guix interactively. +* Invoking guix repl:: Programming Guix in Guile =20 Defining Packages =20 @@ -5472,7 +5472,7 @@ package definitions. * Derivations:: Low-level interface to package derivations. * The Store Monad:: Purely functional interface to the store. * G-Expressions:: Manipulating build expressions. -* Invoking guix repl:: Fiddling with Guix interactively. +* Invoking guix repl:: Programming Guix in Guile @end menu =20 @node Package Modules @@ -8246,12 +8246,47 @@ has an associated gexp compiler, such as a @code{}. @node Invoking guix repl @section Invoking @command{guix repl} =20 -@cindex REPL, read-eval-print loop -The @command{guix repl} command spawns a Guile @dfn{read-eval-print loop} -(REPL) for interactive programming (@pxref{Using Guile Interactively,,, gu= ile, -GNU Guile Reference Manual}). Compared to just launching the @command{gui= le} +@cindex REPL, read-eval-print loop, script +The @command{guix repl} command makes it easier to program Guix in Guile +by launching a Guile @dfn{read-eval-print loop} (REPL) for interactive +programming (@pxref{Using Guile Interactively,,, guile, +GNU Guile Reference Manual}), or by running Guile scripts +(@pxref{Running Guile Scripts,,, guile, +GNU Guile Reference Manual}). +Compared to just launching the @command{guile} command, @command{guix repl} guarantees that all the Guix modules and all = its -dependencies are available in the search path. You can use it this way: +dependencies are available in the search path. + +The general syntax is: + +@example +guix repl @var{options} @var{file} @var{args} +@end example + +When a @var{file} argument is provided, @var{file} is +executed as a Guile scripts: + +@example +guix repl my-script.scm +@end example + +To pass arguments to the script, use @code{--} to prevent them from +being interpreted as arguments to @command{guix repl} itself: + +@example +guix repl -- my-script.scm --input=3Dfoo.txt +@end example + +To make a script executable directly from the shell, using the guix +executable that is on the user's search path, add the following two +lines at the top of the script: + +@example +@code{#!/usr/bin/env -S guix repl --} +@code{!#} +@end example + +Without a file name argument, a Guile REPL is started: =20 @example $ guix repl @@ -8300,7 +8335,7 @@ Add @var{directory} to the front of the package modul= e search path (@pxref{Package Modules}). =20 This allows users to define their own packages and make them visible to -the command-line tool. +the script or REPL. =20 @item -q Inhibit loading of the @file{~/.guile} file. By default, that diff --git a/guix/scripts/repl.scm b/guix/scripts/repl.scm index ff1f208894..4c2537b55d 100644 --- a/guix/scripts/repl.scm +++ b/guix/scripts/repl.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2018, 2019, 2020 Ludovic Court=C3=A8s ;;; Copyright =C2=A9 2020 Simon Tournier +;;; Copyright =C2=A9 2020 Konrad Hinsen ;;; ;;; This file is part of GNU Guix. ;;; @@ -22,6 +23,7 @@ #:use-module (guix scripts) #:use-module (guix repl) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (srfi srfi-37) #:use-module (ice-9 match) #:use-module (rnrs bytevectors) @@ -32,7 +34,8 @@ =20 ;;; Commentary: ;;; -;;; This command provides a Guile REPL +;;; This command provides a Guile script runner and REPL in an environment +;;; that contains all the modules comprising Guix. =20 (define %default-options `((type . guile))) @@ -63,8 +66,9 @@ =20 =20 (define (show-help) - (display (G_ "Usage: guix repl [OPTIONS...] -Start a Guile REPL in the Guix execution environment.\n")) + (display (G_ "Usage: guix repl [OPTIONS...] [-- FILE ARGS...] +In the Guix execution environment, run FILE as a Guile script with +command-line arguments ARGS. If no FILE is given, start a Guile REPL.\n")) (display (G_ " -t, --type=3DTYPE start a REPL of the given TYPE")) (display (G_ " @@ -135,12 +139,13 @@ call THUNK." (define (guix-repl . args) (define opts - ;; Return the list of package names. (args-fold* args %options (lambda (opt name arg result) (leave (G_ "~A: unrecognized option~%") name)) (lambda (arg result) - (leave (G_ "~A: extraneous argument~%") arg)) + (append `((script . ,arg) + (ignore-dot-guile . #t)) + result)) %default-options)) =20 (define user-config @@ -148,28 +153,53 @@ call THUNK." (lambda (home) (string-append home "/.guile")))) =20 + (define (set-user-module) + (set-current-module user-module) + (when (and (not (assoc-ref opts 'ignore-dot-guile?)) + user-config + (file-exists? user-config)) + (load user-config))) + + (define script (reverse + (map cdr + (filter (lambda (opt) + (eq? (car opt) 'script)) + opts)))) + (define script-file + (let ((file (car script)) + (directory (getcwd))) + (canonicalize-path + (cond ((string-prefix? "/" file) file) + (else (string-append directory "/" file)))))) + (with-error-handling - (let ((type (assoc-ref opts 'type))) - (call-with-connection (assoc-ref opts 'listen) - (lambda () - (case type - ((guile) - (save-module-excursion - (lambda () - (set-current-module user-module) - (when (and (not (assoc-ref opts 'ignore-dot-guile?)) - user-config - (file-exists? user-config)) - (load user-config)) - - ;; Do not exit repl on SIGINT. - ((@@ (ice-9 top-repl) call-with-sigint) - (lambda () - (start-repl)))))) - ((machine) - (machine-repl)) - (else - (leave (G_ "~a: unknown type of REPL~%") type)))))))) + + (unless (null? script) + ;; Run script + (save-module-excursion + (lambda () + (set-program-arguments (cons script-file (cdr script))) + (set-user-module) + (load script-file)))) + + (when (null? script) + ;; Start REPL + (let ((type (assoc-ref opts 'type))) + (call-with-connection (assoc-ref opts 'listen) + (lambda () + (case type + ((guile) + (save-module-excursion + (lambda () + (set-user-module) + ;; Do not exit repl on SIGINT. + ((@@ (ice-9 top-repl) call-with-sigint) + (lambda () + (start-repl)))))) + ((machine) + (machine-repl)) + (else + (leave (G_ "~a: unknown type of REPL~%") type))))))))) =20 ;; Local Variables: ;; 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 0000000000..2750188468 --- /dev/null +++ b/tests/guix-repl.sh @@ -0,0 +1,84 @@ +# GNU Guix --- Functional package management for GNU +# Copyright =C2=A9 2020 Simon Tournier +# Copyright =C2=A9 2020 Konrad Hinsen +# +# This file is part of GNU Guix. +# +# GNU Guix 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. +# +# GNU Guix 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 GNU Guix. If not, see . + +# +# Test the `guix repl' command-line utility. +# + +guix repl --version + +test_directory=3D"`mktemp -d`" +export test_directory +trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT + +tmpfile=3D"$test_directory/foo.scm" +rm -f "$tmpfile" +trap 'rm -f "$tmpfile"' EXIT + +module_dir=3D"t-guix-repl-$$" +mkdir "$module_dir" +trap 'rm -rf "$module_dir"' EXIT + + +cat > "$tmpfile"< "$module_dir/foo.scm"< "$tmpfile"< "$tmpfile"< "$tmpfile"<