From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id cBv+G2phRmNV1QAAbAwnHQ (envelope-from ) for ; Wed, 12 Oct 2022 08:40:42 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id SLscHGphRmO5DwEA9RJhRA (envelope-from ) for ; Wed, 12 Oct 2022 08:40:42 +0200 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 066943EE6A for ; Wed, 12 Oct 2022 08:40:42 +0200 (CEST) Received: from localhost ([::1]:44754 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiVQ1-0000GV-0Q for larch@yhetil.org; Wed, 12 Oct 2022 02:40:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32802) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiVPO-0000Fg-25 for guix-patches@gnu.org; Wed, 12 Oct 2022 02:40:03 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:56369) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oiVPN-0003hn-PJ for guix-patches@gnu.org; Wed, 12 Oct 2022 02:40:01 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1oiVPN-0005H0-JX for guix-patches@gnu.org; Wed, 12 Oct 2022 02:40:01 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#58463] [PATCH] * doc: guix-cookbook: Add a "Guix API usage examples" References: In-Reply-To: Resent-From: Fulbert Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Wed, 12 Oct 2022 06:40:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 58463 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 58463@debbugs.gnu.org Received: via spool by 58463-submit@debbugs.gnu.org id=B58463.166555676720219 (code B ref 58463); Wed, 12 Oct 2022 06:40:01 +0000 Received: (at 58463) by debbugs.gnu.org; 12 Oct 2022 06:39:27 +0000 Received: from localhost ([127.0.0.1]:55447 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oiVOo-0005G2-3J for submit@debbugs.gnu.org; Wed, 12 Oct 2022 02:39:27 -0400 Received: from vimdzmsp-sfwd01.bluewin.ch ([195.186.120.131]:33557) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oiVOl-0005Fk-9y for 58463@debbugs.gnu.org; Wed, 12 Oct 2022 02:39:24 -0400 Received: from bluewin.ch ([213.55.244.21]) by vimdzmsp-sfwd01.bluewin.ch Swisscom AG with ESMTPA id iVOdoyVSIaSptiVOeoudv2; Wed, 12 Oct 2022 08:39:17 +0200 X-Bluewin-Spam-Analysis: v=2.4 cv=XueZhXJ9 c=1 sm=1 tr=0 ts=63466115 a=okETWHrkPlANAx00SlWV7w==:117 a=TlOf3hXxsTWzTsQR_ngA:9 a=QEXdDO2ut3YA:10 a=mDV3o1hIAAAA:8 a=CcLUTRNvAAAA:8 a=ZeQmFzkMMxd-BLRRcvoA:9 a=7Zwj6sZBwVKJAoWSPKxL6X1jA+E=:19 a=DzVYJPrVmD-3FXO4:21 a=ZQe0H2SEwV4A:10 a=pxVx6LOZ-VoA:10 a=yavZe7-6PWEA:10 a=Vf4bL7R4lpsA:10 a=Esd8GEl26B8A:10 a=7o4jWxSueEUA:10 a=_FVE-zBwftR9WsbkzFJk:22 a=obhdfE27RNN5ZnF-s2K5:22 X-Bluewin-Spam-Score: 0.00 X-FXIT-IP: IPv4[213.55.244.21] Epoch[1665556757] X-Bluewin-AuthAs: fulbert@bluewin.ch Date: Wed, 12 Oct 2022 08:39:15 +0200 From: Fulbert Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="SJkDfzcMafYJ1CHl" Content-Disposition: inline Content-Transfer-Encoding: 8bit X-CMAE-Envelope: MS4xfGmUVhcyTwyaZhD4CkfMlXmbwU3hCkVPc+lActDFPqBGwXdiViIVG2Ft6l65YHAxSEN7aS6LODM80tCbR1Mcc4BXqZ2Qr742DVOMqVh+5YlEUmptJZRF i4Eab9Ln2Y96Dgog8wYLDEnor3Nn9eX4ghVxZoGy3ADyzl9VwW003wrnCuIb34yC8/uxqcf3YqhAZA== X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list 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-Migadu-Flow: FLOW_IN X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1665556842; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post; bh=asWWejn2HF4636BwITUOXwC2sMSab4uOjGabY5X8kUs=; b=udwvgHohhUGac7APZROfQ1Xt6sGevIN0M9jLxmF0IB9xOqmdqme3NhsOLv48CPlK/by2ND VVlvxH8C9WhKRTeyFAixn8csp7mUMg2JAGIONPqqkVMPboHDQvz2lXfF3pCgHABMdQSUjl nkXsd5pRlC8Ll9D/PfjS0X9iv5kRXGMnKdDGMBjx/v/nt1BAq3Apt55VvScxaD2WH+2AIz 17axy4pVnWTEq+p2kqoIM5+/FdTg0lXLA/YFyUMmFKN8lIoSed0/1UH9yCeCLzXN4jyraS 9KoC52OyPK5XJlrxbX62+ePgkvuWDB/+aItKtHckzeGGxM2Rl2phEu1wrLZ7dQ== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1665556842; a=rsa-sha256; cv=none; b=lC1T2y2umlUv+ZhdEkjmBwCW5MDrcja6Trqb6gCILQdWzn95eq2g/I8x8xdbIqrPjOn+P7 GEI+i4M8lLh9lRvK25uMx6WFI/FYmcIN7nfdEi92QRn3A3DvMDsUIV+z7SS/bo+0tcyU16 Y7Wh0N4Kq2D6vI5DokxzQ3jLzInHW276EEKQAjah7RWPParuReWuwerpReg2YB+G4eTwus C8+M5MAHPbG7aU0s+rEG5/1vXtbldSFmeSqPB8jveU7j/5M4bHuWWJjNMO4aTFJxJLUMz8 dO/pOdHhQpzsSPbSFU0nRxD9o4p67XPaivIfcMqxrJGnyEUJMr7jU2sl+nI+qw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -3.00 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: 066943EE6A X-Spam-Score: -3.00 X-Migadu-Scanner: scn1.migadu.com X-TUID: 7hW4J3/iYbHP --SJkDfzcMafYJ1CHl Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Sorry, I forgot to attach the patch, so here it is. --SJkDfzcMafYJ1CHl Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0001-doc-guix-cookbook-Add-a-Guix-API-usage-examples-chap.patch" Content-Transfer-Encoding: 8bit >From c1af5a6ea0e56d0764969e118f0c55942db90e7b Mon Sep 17 00:00:00 2001 From: Fulbert Date: Wed, 12 Oct 2022 07:57:47 +0200 Subject: [PATCH] * doc: guix-cookbook: Add a "Guix API usage examples" chapter. * doc/guix-cookbook.texi ("Guix API usage examples"): New chapter. Transcript of examples given in "Guix REPL - to infinity and beyond" by Simon Tournier at the "10 years of Guix" event. --- doc/guix-cookbook.texi | 426 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 426 insertions(+) diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi index b61adc06da..8c6954b049 100644 --- a/doc/guix-cookbook.texi +++ b/doc/guix-cookbook.texi @@ -73,6 +73,7 @@ Weblate} (@pxref{Translating Guix,,, guix, GNU Guix reference manual}). * System Configuration:: Customizing the GNU System * Advanced package management:: Power to the users! * Environment management:: Control environment +* API usage examples:: Using the API via REPL, scripts and extensions. * Acknowledgments:: Thanks! * GNU Free Documentation License:: The license of this document. @@ -94,6 +95,11 @@ System Configuration * Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY * Customizing the Kernel:: Creating and using a custom Linux kernel on Guix System. +API usage examples + +* API usage examples:: Using Guix through its API via REPL, script and extensions. + Transcript of Simon Tournier presentation : Guix REPL - to infinity and beyond + @end detailmenu @end menu @@ -2977,6 +2983,426 @@ will have predefined environment variables and procedures. Run @command{direnv allow} to setup the environment for the first time. +@c ********************************************************************* +@node API usage examples +@chapter API usage examples + +This chapter is a transcript of the examples given by Simon Tournier in +his presentation +@uref{https://10years.guix.gnu.org/video/guix-repl-to-infinity-and-beyond/,Guix +REPL - to infinity and beyond} (16 minutes video) at the +@uref{https://10years.guix.gnu.org/,10 years of Guix} event. + +Interactions with Guix as a library through its API via  REPL, script +and ``guix extension'' (API subject to changes, +script/extension might break at any update@dots{}). + +Throuthout this chapter : + +@itemize +@item +shell prompt shortened to : @code{'$ '} +@item +guix REPL prompt shortened to : @code{'> '} +@end itemize + +@menu +* Guix REPL:: +* Guix script:: +* Guix extension:: +@end menu + +@node Guix REPL +@section Guix REPL +@anchor{#guix-repl} + +@menu +* 101:: +* select count packages on criteria:: +* table count/group on criteria:: +@end menu + +@node 101 +@subsection 101 +@anchor{#101} +@quotation Note +the REPL command @code{,use (module path name)} (shortened +@code{,u}) can be used as an equivalent for +@code{(use-modules (module path name))}. @code{,use} alone will list +currently imported modules. +@end quotation + +Simple Guix REPL session +@example sh +$ guix repl +GNU Guile 3.0.8 +;; [skipped licence preamble] +> (use-modules (gnu packages base)) +> findutils +$1 = # +> ,use(guix) +> (package-name findutils) +$2 = "findutils" +> (package-version findutils) +$3 = "4.8.0" +> (package? findutils) +$4 = #t +@end example + +@quotation Note +the REPL command @code{,describe} (can be shortened @code{,d}) : +Usage: describe OBJ@* +Show description/documentation. (#f if unavailable) +@example sh +> ,d package->derivation +Return the object of PACKAGE for SYSTEM. +> ,describe package-name +#f +@end example +@end quotation + +@quotation Note +when a module is imported, its exported objects are listed in +TAB-@dots{} completions. + +@example sh +> package-in +package-input-error? package-input-rewriting/spec +package-input-rewriting package-inputs +@end example +@end quotation + +@node select count packages on criteria +@subsection select count packages on criteria +@anchor{#select-count-packages-on-criteria} +(→ 4 min 20 s into Simon Tournier presentation) + +In the following REPL session + +@itemize +@item +count of haskell packages and ; + +@item +count of haskell pacakges using the @code{#:cabal-revision} argument +@emph{(present in the package ghc-crypthohash-sha1, as shown below, for +instance)} + +@lisp +(define-public ghc-cryptohash-sha1 + (package + ;; skipped for clarity + (build-system haskell-build-system) + (arguments + `(#:cabal-revision + ("6" "10rpxrmqgwihmplczglwxf5q3l13z9j3kvi065z884y4dymmnkgc") + ;; … +@end lisp + +@end itemize + +REPL session : + +@example sh +$ guix repl +GNU Guile 3.0.8 +;; [skipped licence preamble] +> (use-modules + (guix) + (guix build-system haskell) + (gnu) + (ice-9 match)) +> +> (define haskell-packages + (fold-packages + (lambda (package result) + (if (eq? (package-build-system package) haskell-build-system) + (cons package result) + result)) + '())) +> (define (cabal-revision? package) + (apply (lambda* (#:key cabal-revision #:allow-other-keys) + (match cabal-revision + ((revision hash) #t) + (_ #f))) + (package-arguments package))) +> (define cabal-revision-packages + (filter cabal-revision? haskell-packages)) +> (length haskell-packages) +$1 = 721 +> (length cabal-revision-packages) +$2 = 108 +@end example + +@node table count/group on criteria +@subsection table count/group on criteria +@anchor{#table-countgroup-on-criteria} +(→ 5 min 20 s into Simon Tournier presentation) + +The @code{arguments-vs-import.scm} file shown below demonstrate some +more sophisticated selection and grouping of packages, and can be passed +to @code{guix repl} like so : +@example sh +$ guix repl -- arguments-vs-import.scm +@end example +Its interpretation will output a table similar to the one show below the +script-file content, giving the number of packages which ``tweak'' their +arguments to the build and the number of packages which don't, all +grouped by build-system types. + +@code{arguments-vs-import.scm} file content : + +@lisp +(use-modules (guix) + (gnu) + (ice-9 match)) + +(define table (make-hash-table)) + +(fold-packages (lambda (package result) + (let ((bs (build-system-name + (package-build-system package))) + (arg (package-arguments package))) + (match (hash-ref result bs) + ((tot wo wi) + (if (null? arg) + (hash-set! result bs (list + (1+ tot) + (1+ wo) + wi)) + (hash-set! result bs (list + (1+ tot) + wo + (1+ wi))))) + (#f (if (null? arg) + (hash-set! result bs (list 1 1 0)) + (hash-set! result bs (list 1 0 1)))) + (_ (format #t "Error: ~s~%" (package-name package)))) + result)) + table) + +(define fmt "~13s: ~4s = ~4s = ~4s + ~4s~%") +(format #t fmt + 'key 'tot 'tot 'no-arguments 'arguments) +(hash-for-each-handle (lambda (kv) + (match kv + ((key . value) + (match value + ((tot wo wi) + (format #t fmt + key + (+ wo wi) + tot wo wi)))))) + table) +@end lisp + +call from shell and output : + +@example sh +$ cd ~/tmp/10-years-of-guix +$ guix repl -- guix-repl-and-beyond.scm +key : tot = tot = no-arguments + arguments +ocaml : 57 = 57 = 0 + 57 +haskell : 721 = 721 = 504 + 217 +clojure : 11 = 11 = 0 + 11 +[skipping for clarity] +meson : 442 = 442 = 89 + 353 +texlive : 143 = 143 = 0 + 143 +python : 2619 = 2619 = 797 + 1822 +binary : 14 = 14 = 0 + 14 +@end example + +@node Guix script +@section Guix script +@anchor{#guix-script} +Simon Tournier does not say much about using guix through scripts@dots{} +probably because there is not much to say and the following links should +answer most questions. + +@itemize +@item +@uref{https://www.gnu.org/software/guile/manual/html_node/Running-Guile-Scripts.html#Running-Guile-Scripts,Running +Guile Scripts (Guile Reference Manual)} +@item +@uref{https://www.gnu.org/software/guile/manual/html_node/Guile-Scripting.html#Guile-Scripting,Guile +Scripting (Guile Reference Manual)} +@item +@uref{https://www.gnu.org/software/coreutils/manual/html_node/env-invocation.html#env-invocation,env +invocation (GNU Coreutils 9.1)} +@end itemize + +Nevertheless, the script ``@code{explore}'', from Ludovic Courtès, used +in the next section to demonstrate a ``script-to-extension conversion'', +is probably an interesting example of using the guix API. See the links +below for more : + +@itemize +@item +@uref{https://10years.guix.gnu.org/video/explore-your-system/,Ten Years +of Guix --- Explore your system --- Ludovic Courtès} +@item +@uref{https://notabug.org/civodul/guix-explorer,civodul/guix-explorer: +Exploring Guix System. - NotABug.org: Free code hosting} +@end itemize + +@node Guix extension +@section Guix extension +@anchor{#guix-extension} +(→ 7 min 05 s into Simon Tournier presentation) + +@menu +* minimal example:: +* Ludovic Courtès's explore.scm program:: +@end menu + +@node minimal example +@subsection minimal example +@anchor{#minimal-example} +As a minimal example of a guix extension, the following file, +@code{~/tmp/10-years-of-guix/guix/extensions/hello.scm}, is used : + +@lisp +(define-module (guix extensions hello) + #:export (guix-hello)) + +(define-command (guix-hello . cmd-line) + (category plumbing) + (synopsis "hello world") + (display (G_ "hello folks!"))) +@end lisp + +The environment variable @code{GUIX_EXTENSIONS_PATH} has to include the +path to the scrip file. + +With this in place, we can see the @code{hello} extension integrated in +the @code{guix} CLI, as the following capture shows, with the new +command ``hello'' added to the ``plumbing'' category : + +@example sh +$ export GUIX_EXTENSIONS_PATH="$HOME/tmp/10-years-of-guix/guix/extensions" +$ guix help +Usage: guix OPTION | COMMAND ARGS... +Run COMMAND with ARGS, if given. +# [skipping for clarity …] + plumbing commands + archive manipulate, export, and import normalized archives (nars) + copy copy store items remotely over SSH + git operate on Git repositories + offload set up and operate build offloading + processes list currently running sessions + repl read-eval-print loop (REPL) for interactive programming + hello hello world + +Report bugs to: bug-guix@@gnu.org. +# … +@end example + +@node Ludovic Courtès's explore.scm program +@subsection Ludovic Courtès's explore.scm program +@anchor{#ludovic-courtèss-explore.scm-program} +The @code{explore.scm} script can then be modified as follows to have it work +as a Guix extension rather than a script. + +(→ 9 min 13 s into Simon Tournier presentation) + +@itemize +@item +removing the shebang call to guile + +@example +@verbatim +-#!/bin/sh +-exec "${GUILE:-guile}" -e "(@ (explore) guix-explore)" -s "$0" "$@" +-!# +@end verbatim +@end example + +@item +replacing the module declaration with appropriate path/name +@example +@verbatim +-(define-module (explore) ++(define-module (guix extensions explore) +@end verbatim +@end example + +@item +adding the module guix scripts to the use-module list +@example +@dots{} +@verbatim + #:use-module (guix ui) ++ #:use-module (guix scripts) + #:use-module (guix store) +@end verbatim +@dots{} +@end example + +@item +modifying the guix-explore definition +@example +@verbatim +-(define (guix-explore args) ++(define-command (guix-explore . args) ++ (category extension) ++ (synopsis ``explore your service'') +(define %user-module @dots{} +@end verbatim +@dots{} +@end example +@end itemize + +@quotation Note on the path to the script + +[It seems that] to be used as a guix extension, Guix requires a script +to live under a +``[/@dots{}]/guix/extensions[/@dots{}]/.scm'' tree +structure with the corresponding module declaration +@code{(define-module (guix extensions [@dots{}] ) @dots{}}. + +This will work : + +@example sh +$ pwd +~/tmp/10-years-of-guix/guix/extensions/test +$ head -1 hello.scm +(define-module (guix extensions test hello) +@end example + +@dots{} while this won't work : + +@example sh +$ pwd +~/tmp/10-years-of-guix/guix/test +$ head -1 hello.scm +(define-module (guix test hello) +@end example + +@dots{} nor this : + +@example sh +$ pwd +~/tmp/10-years-of-guix/nono/ +$ head -1 hello.scm +(define-module (nono hello) +@end example +@end quotation + +lauching + +@quotation Note +@code{explore} produces a visual and interactive representation of +the services used in a OS declaration. The user has to provide a path to +the OS configuration file to explore. +@end quotation + +All set, explore can now be used as a Guix extension like so : + +@example sh +$ export GUIX_EXTENSIONS_PATH=/path/to/guix/extensions +$ guix explore -- /path/to/configure.scm +@end example + @c ********************************************************************* @node Acknowledgments @chapter Acknowledgments -- 2.38.0 --SJkDfzcMafYJ1CHl--