diff mbox series

[bug#40373] guix: new command "guix run-script"

Message ID m1d08rmh6g.fsf@khs-macbook.home
State Accepted
Headers show
Series [bug#40373] guix: new command "guix run-script" | expand

Checks

Context Check Description
cbaines/comparison success View comparision
cbaines/git branch success View Git branch
cbaines/applying patch success View Laminar job

Commit Message

Konrad Hinsen April 1, 2020, 2:09 p.m. UTC
* guix/scripts/run-script.scm: New file.
* Makefile.am: (MODULES): Add it.
* doc/guix.texi: Document "guix time-machine"
---
 Makefile.am                 |   1 +
 doc/guix.texi               |  32 +++++++++++
 guix/scripts/run-script.scm | 106 ++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+)
 create mode 100644 guix/scripts/run-script.scm

Comments

Ludovic Courtès April 1, 2020, 9 p.m. UTC | #1
Hi Konrad,

Konrad Hinsen <konrad.hinsen@fastmail.net> skribis:

> +The @command{guix run-script} command executes a Guile script
> +(@pxref{Running Guile Scripts,,, guile, GNU Guile Reference Manual}).
> +Compared to just launching the @command{guile} command,
> +@command{guix run-script} guarantees that all the Guix modules
> +and all its dependencies are available in the search path.

What about making that just a new ‘-s’ flag for ‘guix repl’ (just like
Guile’s ‘-s’ flag)?  ‘-q’ should always be implied when doing that.

Now, this wouldn’t be usable as a shebang due to the fact that only one
argument is allowed, unless we do some extra argument tokenizing.

Thanks,
Ludo’.
Konrad Hinsen April 2, 2020, 7:13 a.m. UTC | #2
Hi Ludo,

> What about making that just a new ‘-s’ flag for ‘guix repl’ (just like
> Guile’s ‘-s’ flag)?  ‘-q’ should always be implied when doing that.
>
> Now, this wouldn’t be usable as a shebang due to the fact that only one
> argument is allowed, unless we do some extra argument tokenizing.

That is one reason why I opted for a separate command.

The other is that I am in tutorial-driven development mode: I need "guix
run-script" in order to be able to insert my own scripts (for analyzing
dependencies) into a Guix tutorial for an upcoming MOOC. So I need to
make sure that people can run my scripts easily, but also that they
understand what they are doing. A command that does something else than
its name suggests, with a similarity that is only visible to experts,
is no good for use in a tutorial.

BTW, I opted for a lengthy name ("run-script" rather than just "run" or
"script") according to the principle that short words should be left for
frequently used concepts (a principle respected by human languages, but
also by Lisp tradition).

I am of course aware that much of the code in "run-script" is the same
as in "repl", which is not good. But I'd rather think about a better
framework for code sharing among Guix scripts than about pushing too
much semantic differences into obscure options. An example would be
reusable "option clusters", such as "options for Guile" or "options for
channels".

Cheers,
  Konrad.
Simon Tournier April 2, 2020, 9:08 a.m. UTC | #3
Hi Konrad,

On Wed, 1 Apr 2020 at 16:10, Konrad Hinsen <konrad.hinsen@fastmail.net> wrote:
>
> * guix/scripts/run-script.scm: New file.
> * Makefile.am: (MODULES): Add it.
> * doc/guix.texi: Document "guix time-machine"

Wrong copy/paste?
Is it not "run-script" instead of "time-machine"?


> --- /dev/null
> +++ b/guix/scripts/run-script.scm
> @@ -0,0 +1,106 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
> +;;; Copyright © 2020 Konrad Hinsen <konrad.hinsen@fastmail.net>

Why Copyright 2018, 2019 is the file is new?
And why Ludo is mentioned here?



Cheers,
simon
Simon Tournier April 2, 2020, 9:17 a.m. UTC | #4
Hi Konrad,

On Thu, 2 Apr 2020 at 09:14, Konrad Hinsen <konrad.hinsen@fastmail.net> wrote:

> > What about making that just a new ‘-s’ flag for ‘guix repl’ (just like
> > Guile’s ‘-s’ flag)?  ‘-q’ should always be implied when doing that.
> >
> > Now, this wouldn’t be usable as a shebang due to the fact that only one
> > argument is allowed, unless we do some extra argument tokenizing.
>
> That is one reason why I opted for a separate command.
>
> The other is that I am in tutorial-driven development mode: I need "guix
> run-script" in order to be able to insert my own scripts (for analyzing
> dependencies) into a Guix tutorial for an upcoming MOOC. So I need to
> make sure that people can run my scripts easily, but also that they
> understand what they are doing. A command that does something else than
> its name suggests, with a similarity that is only visible to experts,
> is no good for use in a tutorial.
>
> BTW, I opted for a lengthy name ("run-script" rather than just "run" or
> "script") according to the principle that short words should be left for
> frequently used concepts (a principle respected by human languages, but
> also by Lisp tradition).
>
> I am of course aware that much of the code in "run-script" is the same
> as in "repl", which is not good. But I'd rather think about a better
> framework for code sharing among Guix scripts than about pushing too
> much semantic differences into obscure options. An example would be
> reusable "option clusters", such as "options for Guile" or "options for
> channels".

Initially, I thought the same as Ludo: "run-script" should be an
option to "repl". And I understand your UI concerns.

Maybe, we could deprecated "repl" and add "run" with:
 - guix run <file> (same than the "guix run-script" proposal)
 - guix run or guix run --repl doing the what "guix repl" does.

The new command "guix run" could have more or less the same option
than "guile" but prepending all the paths correctly. I mean we need
something like "guix name-it <otpions>" mimicking "guile <options>"
adding the correct Guix modules, IMHO.


BTW, thank you for this. Because it was missing in my toolbox and I
was annoyed until now.


Cheers,
simon
Konrad Hinsen April 2, 2020, 9:21 a.m. UTC | #5
Hi Simon,

> Wrong copy/paste?

Exactly. Same for the next point. Update coming.

Cheers,
  Konrad.
Konrad Hinsen April 2, 2020, 9:37 a.m. UTC | #6
Hi Simon,

> Maybe, we could deprecated "repl" and add "run" with:
>  - guix run <file> (same than the "guix run-script" proposal)
>  - guix run or guix run --repl doing the what "guix repl" does.

Yes, unifying the two functionalities under a new name is an interesting
options.

Could we go for "guix guile" and make it option-compatible with plain
Guile as much as possible? Just an idea, I am not sure it's a good one!
Guile can already be a pain in a shebang line.

Cheers,
  Konrad
Konrad Hinsen April 3, 2020, 9:17 a.m. UTC | #7
Konrad Hinsen <konrad.hinsen@fastmail.net> writes:

> Could we go for "guix guile" and make it option-compatible with plain
> Guile as much as possible? Just an idea, I am not sure it's a good one!
> Guile can already be a pain in a shebang line.

After some exploration, that kind of compatibility doesn't seem worth
the effort.

I will send another patch that implements Simon's proposal:

 - New command "guix run" that extends "guix repl" by an optional
   file argument for running a script.
 - "guix repl" becomes an alias for "guix run" (and could in the
   long run be declared obsolete).

Cheers,
  Konrad.
Ludovic Courtès April 3, 2020, 9:48 a.m. UTC | #8
Hi Konrad,

Konrad Hinsen <konrad.hinsen@fastmail.net> skribis:

> Konrad Hinsen <konrad.hinsen@fastmail.net> writes:
>
>> Could we go for "guix guile" and make it option-compatible with plain
>> Guile as much as possible? Just an idea, I am not sure it's a good one!
>> Guile can already be a pain in a shebang line.
>
> After some exploration, that kind of compatibility doesn't seem worth
> the effort.
>
> I will send another patch that implements Simon's proposal:
>
>  - New command "guix run" that extends "guix repl" by an optional
>    file argument for running a script.

“guix run” was sort of reserved for something else:

  https://lists.gnu.org/archive/html/help-guix/2018-01/msg00118.html

The idea is still floating around so perhaps we should keep that name.

>  - "guix repl" becomes an alias for "guix run" (and could in the
>    long run be declared obsolete).

I’m worried about a possible increase of the deprecation rate.  I
understand the rationale, I think it makes sense, but still, I’m not
sure we need to deprecate “guix repl” already.

In fact, since it’s used by inferiors, we must pay extra attention to
keep it as-is as much as possible or we’ll make communication between
old and new Guixes difficult.

Thoughts?

Thanks,
Ludo’.
Ludovic Courtès April 3, 2020, 9:51 a.m. UTC | #9
Hello,

Konrad Hinsen <konrad.hinsen@fastmail.net> skribis:

> The other is that I am in tutorial-driven development mode: I need "guix
> run-script" in order to be able to insert my own scripts (for analyzing
> dependencies) into a Guix tutorial for an upcoming MOOC. So I need to
> make sure that people can run my scripts easily, but also that they
> understand what they are doing. A command that does something else than
> its name suggests, with a similarity that is only visible to experts,
> is no good for use in a tutorial.

I see.  (I have to ponder this a bit more.)

> I am of course aware that much of the code in "run-script" is the same
> as in "repl", which is not good.

Yes, we can probably factorize a bit.  We must make sure ‘-q’ is not
implemented by this command; ‘-t’ is also useless.

> But I'd rather think about a better framework for code sharing among
> Guix scripts than about pushing too much semantic differences into
> obscure options. An example would be reusable "option clusters", such
> as "options for Guile" or "options for channels".

We do have that with ‘%standard-build-options’, for instance, although
not as nicely-structured as we’d like (in general, I’d prefer to have a
GNU argp-style command-line API than what we have).

Ludo’.
Konrad Hinsen April 7, 2020, 9:10 a.m. UTC | #10
Hi Ludo,

>> I am of course aware that much of the code in "run-script" is the same
>> as in "repl", which is not good.
>
> Yes, we can probably factorize a bit.  We must make sure ‘-q’ is not
> implemented by this command; ‘-t’ is also useless.

Right.

> We do have that with ‘%standard-build-options’, for instance, although
> not as nicely-structured as we’d like (in general, I’d prefer to have a
> GNU argp-style command-line API than what we have).

It would also be nice to share the documentation for these options among
different scripts. That's actually more lines of code than the code
itself.

More generally, it would be nice to decouple implementation decisions
from user interface decisions. Git provides a nice example of what
happens when user interface design follows ease of implementation
criteria for a while. It's probably the most hated essential piece of
software by now.

From a user interface point of view, it is preferable to have many
commands with clear names, rather than few commands overloaded with
multiple functions selected by cryptic options.

Cheers,
  Konrad
Ludovic Courtès April 7, 2020, 10:36 a.m. UTC | #11
Hello,

Konrad Hinsen <konrad.hinsen@fastmail.net> skribis:

> From a user interface point of view, it is preferable to have many
> commands with clear names, rather than few commands overloaded with
> multiple functions selected by cryptic options.

I agree overall, though it’s not black and white: the benefit of having
separate commands weakens as they proliferate.  A new command may be
more difficult to discover than an option to an existing command.

But anyway, let’s see how we can get ‘run-script’ in!  :-)

Thanks,
Ludo’.
Simon Tournier April 17, 2020, 11:21 a.m. UTC | #12
Dear,

Naming is hard. :-)

Why not simply add an option to "guix repl"?
For example "--batch", mimicking  "emacs --batch".
Or "--script".

Or "guix repl <file>" just run the <file> as the proposed "guix run-script"?


I do not have the feeling that adding a new subcommand is mandatory.
But running a script using the Guix modules is really useful, I always
complain to myself of this lacking feature. :-)


Cheers,
simon
Konrad Hinsen April 23, 2020, 10:12 a.m. UTC | #13
Hi Simon,

> Why not simply add an option to "guix repl"?
> For example "--batch", mimicking  "emacs --batch".
> Or "--script".

Do you have a suggestion for explaining such a command to someone who
want to run a script bu (1) doesn't know what a REPL is, (2) doesn't
need to know what a REPL is, (3) would be mystified by the behavior
resulting from forgetting the –script argument?

I agree of course that naming is hard, but it is also important.  Git
should be a sufficient demonstration of what happens when you design
command-line interfaces by a sequence of cumulative least-effort
decisions.

Cheers,
  Konrad
Simon Tournier April 23, 2020, 2:41 p.m. UTC | #14
Hi Konrad,

On Thu, 23 Apr 2020 at 12:13, Konrad Hinsen <konrad.hinsen@fastmail.net> wrote:

> > Why not simply add an option to "guix repl"?
> > For example "--batch", mimicking  "emacs --batch".
> > Or "--script".
>
> Do you have a suggestion for explaining such a command to someone who
> want to run a script bu (1) doesn't know what a REPL is, (2) doesn't
> need to know what a REPL is, (3) would be mystified by the behavior
> resulting from forgetting the –script argument?

If I understand well
     guix run-script file1 file2
is becoming:
    guix repl --script=file1,file2,...
right?

Well, I would say that

--8<---------------cut here---------------start------------->8---
the keyword "repl" stand for Read-Eval-Print-Loop
therefore the command will:
  - read the script file1,
  - eval it,
  - print the results if they are,
  - and finally loop if there is more than one script file.
--8<---------------cut here---------------end--------------->8---

this fills the condition (1) and (2); at least to me. ;-)


I agree that forgetting the argument '--script' could mystified the learner.

But applying the same principles, the command
    guix environment --ad-hoc python -- python
could mystified the learner too, if for example they forgets --ad-hoc
or '-- python'.

Well, this kind of disconcerting "mistakes" is part of the learning
process, IMHO.
Others call that "discoverability". ;-)


> I agree of course that naming is hard, but it is also important.  Git
> should be a sufficient demonstration of what happens when you design
> command-line interfaces by a sequence of cumulative least-effort
> decisions.

I agree.
And I still have in my stack how to propose another CLI naming as we
discussed earlier, e.g.,
    environment, package, etc.
reorganized into
  profile, install, search, etc.


Cheers,
sion
Konrad Hinsen April 29, 2020, 4:04 p.m. UTC | #15
Hi Simon,

> If I understand well
>      guix run-script file1 file2
> is becoming:
>     guix repl --script=file1,file2,...
> right?
>
> Well, I would say that
>
> --8<---------------cut here---------------start------------->8---
> the keyword "repl" stand for Read-Eval-Print-Loop
> therefore the command will:
>   - read the script file1,
>   - eval it,
>   - print the results if they are,
>   - and finally loop if there is more than one script file.
> --8<---------------cut here---------------end--------------->8---

That's very clever! The weak spot is the P, as script evaluation does
not print anything. We could make it print the script's return code ;-)

> But applying the same principles, the command
>     guix environment --ad-hoc python -- python
> could mystified the learner too, if for example they forgets --ad-hoc
> or '-- python'.

Indeed. I never said that existing Guix commands are perfect ;-)
In fact, I remember some debate about precisely the case of "guix
environment".

> And I still have in my stack how to propose another CLI naming as we
> discussed earlier, e.g.,
>     environment, package, etc.
> reorganized into
>   profile, install, search, etc.

The CLI as an eternal construction site ;-)

Cheers,
  Konrad
Simon Tournier April 30, 2020, 12:42 p.m. UTC | #16
Hi Konrad,

On Wed, 29 Apr 2020 at 18:04, Konrad Hinsen <konrad.hinsen@fastmail.net> wrote:

> That's very clever! The weak spot is the P, as script evaluation does
> not print anything. We could make it print the script's return code ;-)

Hum? The usual REPL neither. :-)
Quoting Wikipedia: "print function takes the result yielded by eval"
but from my understanding 'eval' does not always yield a "printable"
result, e.g., "(define foo 42)".


Cheers,
simon
Konrad Hinsen May 4, 2020, 1:54 p.m. UTC | #17
Hi Simon,

>> That's very clever! The weak spot is the P, as script evaluation does
>> not print anything. We could make it print the script's return code ;-)
>
> Hum? The usual REPL neither. :-)

You mean... they have been LYING to us all the time... about the REPL?

> Quoting Wikipedia: "print function takes the result yielded by eval"
> but from my understanding 'eval' does not always yield a "printable"
> result, e.g., "(define foo 42)".

True, not always. But for scripts it's never. We have to find some nice
three-valued logic rhetoric that applies to all situations ;-)

Command line:
  - read an expression,
  - eval it,
  - print the result of the evaluation (if any),
  - and finally loop to process the next expression

Scripts:
  - read the script file1,
  - eval it,
  - print the textual output of the script (if any),
  - and finally loop if there is more than one script file.

That makes "print" look optional in both cases.

Cheers,
  Konrad.
Simon Tournier May 4, 2020, 5:48 p.m. UTC | #18
Hi Konrad,

On Mon, 4 May 2020 at 15:55, Konrad Hinsen <konrad.hinsen@fastmail.net> wrote:

> True, not always. But for scripts it's never. We have to find some nice
> three-valued logic rhetoric that applies to all situations ;-)
>
> Command line:
>   - read an expression,
>   - eval it,
>   - print the result of the evaluation (if any),
>   - and finally loop to process the next expression
>
> Scripts:
>   - read the script file1,
>   - eval it,
>   - print the textual output of the script (if any),
>   - and finally loop if there is more than one script file.
>
> That makes "print" look optional in both cases.

It is how I personally understand all that. :-)
So that's why I proposed "guix repl --script" (in short '-s') ;-)

In this frame of "guix repl", the future additions/evolution could be:

  --eval,-e for evaluating one expression just after the script is loaded
  --debug for starting the "debugging" VM engine (personally never
used with Guile)
  --language for switching to WISP (optimistic evolution of GWL :-))
  --use-srfi for loading SRFI modules

So it ends up with this kind of command-line:

  guix repl -L /path/to/stuff --use-srfi=9
  guix repl -L /path/to/custom -s file.scm
  guix repl --language=wisp --script file.wsp
  guix repl -s file.scm -e '(package-name foo)'

Well, 'repl' meaning "use the interpreter in the context of Guix".
Is 'repl' enough meaningful for these use cases? Personally, I think so. :-)


All the best,
simon
Konrad Hinsen May 14, 2020, 9:29 a.m. UTC | #19
Hi everyone,

Since this proposition does not seem to be going anywhere, I have
submitted an alternative patch as bug#41253 which simply adds script
execution to "guix repl", with no changes to the existing behavior, nor
any new command. For my tutorial, I will use shell scripts that hide the
guix command line from view, so that I do not have to explain it.

This bug can thus be closed, and I'd have done it already if I knew
how. I couldn't find any instructions.

Cheers,
  Konrad.
Simon Tournier May 14, 2020, 9:44 a.m. UTC | #20
Hi Konrad,

On Thu, 14 May 2020 at 11:30, Konrad Hinsen <konrad.hinsen@fastmail.net> wrote:

> Since this proposition does not seem to be going anywhere, I have
> submitted an alternative patch as bug#41253 which simply adds script
> execution to "guix repl", with no changes to the existing behavior, nor
> any new command. For my tutorial, I will use shell scripts that hide the
> guix command line from view, so that I do not have to explain it.

Cool!

> This bug can thus be closed, and I'd have done it already if I knew
> how. I couldn't find any instructions.

Two ways:
 - answer to 40373-done@debbugs.gnu.org; as it is done here.
 - send to controls@debbugs.gnu.org with the body:
       close 30373
       thanks

https://debbugs.gnu.org/server-control.html

Cheers,
simon
diff mbox series

Patch

diff --git a/Makefile.am b/Makefile.am
index 344ecdbc42..28ac7344e8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -283,6 +283,7 @@  MODULES =					\
   guix/scripts/container/exec.scm		\
   guix/scripts/deploy.scm			\
   guix/scripts/time-machine.scm			\
+  guix/scripts/run-script.scm			\
   guix.scm					\
   $(GNU_SYSTEM_MODULES)
 
diff --git a/doc/guix.texi b/doc/guix.texi
index 8cb85fe62c..0a64af24dc 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -235,6 +235,7 @@  Programming Interface
 * The Store Monad::             Purely functional interface to the store.
 * G-Expressions::               Manipulating build expressions.
 * Invoking guix repl::          Fiddling with Guix interactively.
+* Invoking guix run-script::    Running Guix scripts.
 
 Defining Packages
 
@@ -5347,6 +5348,7 @@  package definitions.
 * The Store Monad::             Purely functional interface to the store.
 * G-Expressions::               Manipulating build expressions.
 * Invoking guix repl::          Fiddling with Guix interactively.
+* Invoking guix run-script::    Running Guix scripts.
 @end menu
 
 @node Package Modules
@@ -8121,6 +8123,36 @@  Inhibit loading of the @file{~/.guile} file.  By default, that
 configuration file is loaded when spawning a @code{guile} REPL.
 @end table
 
+@node Invoking guix run-script
+@section Invoking @command{guix run-script}
+
+@cindex script
+
+The @command{guix run-script} command executes a Guile script
+(@pxref{Running Guile Scripts,,, guile, GNU Guile Reference Manual}).
+Compared to just launching the @command{guile} command,
+@command{guix run-script} guarantees that all the Guix modules
+and all its dependencies are available in the search path.
+
+The general syntax is:
+
+@example
+guix run-script @var{options} @var{file}
+@end example
+
+The available options are as follows:
+
+@table @code
+@item --load-path=@var{directory}
+@itemx -L @var{directory}
+Add @var{directory} to the front of the package module search path
+(@pxref{Package Modules}).
+
+@item -q
+Inhibit loading of the @file{~/.guile} file.  By default, that
+configuration file is loaded before executing the script.
+@end table
+
 @c *********************************************************************
 @node Utilities
 @chapter Utilities
diff --git a/guix/scripts/run-script.scm b/guix/scripts/run-script.scm
new file mode 100644
index 0000000000..2e948da85f
--- /dev/null
+++ b/guix/scripts/run-script.scm
@@ -0,0 +1,106 @@ 
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2020 Konrad Hinsen <konrad.hinsen@fastmail.net>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts run-script)
+  #:use-module (guix ui)
+  #:use-module (guix scripts)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-37)
+  #:use-module (ice-9 match)
+  #:export (guix-run-script))
+
+;;; Commentary:
+;;;
+;;; This command allows to run Guile scripts in an environment
+;;; that contains all the modules comprising Guix.
+
+(define %default-options
+  '())
+
+(define %options
+  (list (option '(#\h "help") #f #f
+                (lambda args
+                  (show-help)
+                  (exit 0)))
+        (option '(#\V "version") #f #f
+                (lambda args
+                  (show-version-and-exit "guix run-script")))
+        (option '(#\q) #f #f
+                (lambda (opt name arg result)
+                  (alist-cons 'ignore-dot-guile? #t result)))
+        (option '(#\L "load-path") #t #f
+                (lambda (opt name arg result)
+                  ;; XXX: Imperatively modify the search paths.
+                  (set! %load-path (cons arg %load-path))
+                  (set! %load-compiled-path (cons arg %load-compiled-path))
+                  result))))
+
+
+(define (show-help)
+  (display (G_ "Usage: guix run-script [OPTIONS...] FILE
+Run FILE as a Guile script in the Guix execution environment.\n"))
+  (display (G_ "
+  -q                     inhibit loading of ~/.guile"))
+  (newline)
+  (display (G_ "
+  -L, --load-path=DIR    prepend DIR to the package module search path"))
+  (newline)
+  (display (G_ "
+  -h, --help             display this help and exit"))
+  (display (G_ "
+  -V, --version          display version information and exit"))
+  (newline)
+  (show-bug-report-information))
+
+(define user-module
+  ;; Module where we execute user code.
+  (let ((module (resolve-module '(guix-user) #f #f #:ensure #t)))
+    (beautify-user-module! module)
+    module))
+
+
+(define (guix-run-script . args)
+  (define opts
+    (args-fold* args %options
+                (lambda (opt name arg result)
+                  (leave (G_ "~A: unrecognized option~%") name))
+                (lambda (arg result)
+                  (when (assq 'argument result)
+                    (leave (G_ "~A: extraneous argument~%") arg))
+                  (alist-cons 'argument arg result))
+                %default-options))
+
+  (define script
+    (or (assq-ref opts 'argument)
+        (leave (G_ "no script filename specified~%"))))
+
+  (define user-config
+    (and=> (getenv "HOME")
+           (lambda (home)
+             (string-append home "/.guile"))))
+
+  (with-error-handling
+    (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))
+       (load script)))))