Message ID | m1d08rmh6g.fsf@khs-macbook.home |
---|---|
State | Accepted |
Headers | show |
Series | [bug#40373] guix: new command "guix run-script" | expand |
Context | Check | Description |
---|---|---|
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
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’.
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.
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
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
Hi Simon,
> Wrong copy/paste?
Exactly. Same for the next point. Update coming.
Cheers,
Konrad.
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 <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.
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’.
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’.
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
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’.
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
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
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
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
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
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.
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
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.
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 --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)))))