From mboxrd@z Thu Jan 1 00:00:00 1970 From: Efraim Flashner Subject: Re: Adding wc to Bournish Date: Tue, 14 Jun 2016 12:27:13 +0300 Message-ID: <20160614092713.GA2832@debian-netbook> References: <20160524184720.GA27449@debian-netbook> <20160605124033.GB859@debian-netbook> <87eg8bpe2v.fsf@gnu.org> <20160607074155.GB32264@debian-netbook> <878tyfelf6.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="SkvwRMAIpAhPCcCJ" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:54538) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCkd8-0007Qw-Ns for guix-devel@gnu.org; Tue, 14 Jun 2016 05:27:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bCkd4-00007T-Dz for guix-devel@gnu.org; Tue, 14 Jun 2016 05:27:29 -0400 Content-Disposition: inline In-Reply-To: <878tyfelf6.fsf@gnu.org> List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: Ludovic =?utf-8?Q?Court=C3=A8s?= Cc: guix-devel@gnu.org --SkvwRMAIpAhPCcCJ Content-Type: multipart/mixed; boundary="9jxsPFA5p3P2qPhR" Content-Disposition: inline --9jxsPFA5p3P2qPhR Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Wed, Jun 08, 2016 at 05:43:09PM +0200, Ludovic Court=C3=A8s wrote: > Efraim Flashner skribis: >=20 > > On Sun, Jun 05, 2016 at 10:37:12PM +0200, Ludovic Court=C3=A8s wrote: >=20 > [...] >=20 > >> I=E2=80=99ll commit a couple of fixes for bugs I just found and that p= revent us > >> from doing: > >>=20 > >> (compile "ls" #:from %bournish-language #:to 'scheme). >=20 > (This should be be =E2=80=98read-and-compile=E2=80=99, not =E2=80=98compi= le=E2=80=99.) >=20 > Done in f82c58539e1f7b9b864e68ea2ab0c6a17c15fbb5. Take a look at > tests/bournish.scm for examples of what is expected. >=20 ok > > From ebce5076177314bfd17a53019b3f6b6888762b01 Mon Sep 17 00:00:00 2001 > > From: Efraim Flashner > > Date: Sun, 22 May 2016 14:56:06 +0300 > > Subject: [PATCH] bournish: Add `wc' command. > > > > * guix/build/bournish.scm (file-size, wc-c-command, wc-l-command, > > lines+chars, wc-command, wc-command-implementation): New variables. > > (%commands): Add wc command. >=20 > [...] >=20 > > +(define* (wc-command-implementation filelist #:optional args) >=20 > =E2=80=98files=E2=80=99, not =E2=80=98filelist=E2=80=99. >=20 ok > > + (let ((files (filter (lambda (file) > > + (catch 'system-error > > + (lambda () > > + (lstat file)) > > + (lambda args > > + (let ((errno (system-error-errno args))) > > + (format (current-error-port) "~a: ~a~%" > > + file (strerror errno)) > > + #f)))) >=20 > =E2=80=98stat=E2=80=99 rather than =E2=80=98fstat=E2=80=99. >=20 ok > > + (for-each > > + (lambda (file) > > + (let-values (((lines chars) > > + (call-with-input-file file lines+chars))) > > + (match args > > + (#\l > > + (format #t "~a ~a~%" lines file)) > > + (#\c > > + (format #t "~a ~a~%" chars file)) > > + (_ > > + (format #t "~a ~a ~a~%" lines chars file))))) > > + files))) >=20 > OK. >=20 In the end I went with 3 separate functions for the three commands (`wc', `wc -l', `wc -c') like you mentioned later. > > +(define (wc-command args . rest) > > + (let* ((flags (cond ((string=3D? args "-l") #\l) > > + ((string=3D? args "-c") #\c) > > + (else #\nul)))) ; no flags, "args" is a file >=20 > I=E2=80=99d rather make it: >=20 > (define (wc-commands . args) > (cond ((member "-l" args) =E2=80=A6) > ((member "-c" args) =E2=80=A6) > (else =E2=80=A6))) >=20 > Instead of the #\nul thing, I think it=E2=80=99d be best to have separate > procedures for -l, -c, and the other case. This also looks nicer, and I was able to strip the `-l' or `-c' before passing the ,args to the implementation function. >=20 > > + ((@@ (guix build bournish) wc-command-implementation) > > + (if (char=3D? flags #\nul) (cons args rest) rest) flags))) >=20 > This is still not emitting code. :-) IOW, there should be a quasiquote > here. >=20 > You can see that by running: >=20 > (use-modules (system base compile) (guix build bournish)) > (read-and-compile (open-input-string "wc -l foo") > #:from %bournish-language #:to 'scheme) >=20 > This should return something like: >=20 > `((@ (guix build bournish) wc-l-command-implementation) '("foo")) >=20 got this one fixed, which in turn broke the implementation code ;) In the end I went with not a list, so it came out like this: scheme@(guile-user)> (read-and-compile (open-input-string "wc -l foo bar ba= z") #:from %bournish-language #:to 'scheme) $1 =3D ((@@ (guix build bournish) wc-l-command-implementation) "foo" "bar" = "baz") > Makes sense? We=E2=80=99re almost done. >=20 > Please take a look at > > to make the last review super fast. ;-) >=20 > Thank you! >=20 > Ludo=E2=80=99. I've attached what hopefully is the last patch for wc :) I took (and put somewhere safe) the other code I wrote that does wc-c by calling (stat file) and the one for wc-l that opens the file as a port and reads for #\newlines. --=20 Efraim Flashner =D7=90=D7=A4=D7=A8=D7=99=D7=9D = =D7=A4=D7=9C=D7=A9=D7=A0=D7=A8 GPG key =3D A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351 Confidentiality cannot be guaranteed on emails sent or received unencrypted --9jxsPFA5p3P2qPhR Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0001-bournish-Add-wc-command.patch" Content-Transfer-Encoding: quoted-printable =46rom 60a473e123a5da4e3592c67aae8002bf11cca633 Mon Sep 17 00:00:00 2001 =46rom: Efraim Flashner Date: Sun, 22 May 2016 14:56:06 +0300 Subject: [PATCH] bournish: Add `wc' command. * guix/build/bournish.scm (lines+chars, wc-commands, wc-command-implementation, wc-l-command-implementation, wc-c-command-implementation): New variables. (%commands): Add wc command. --- guix/build/bournish.scm | 79 +++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/guix/build/bournish.scm b/guix/build/bournish.scm index 1f17e0a..a4c5b83 100644 --- a/guix/build/bournish.scm +++ b/guix/build/bournish.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2016 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2016 Efraim Flashner ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,6 +26,7 @@ #:use-module (ice-9 match) #:use-module (ice-9 ftw) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) #:export (%bournish-language)) =20 @@ -103,6 +105,80 @@ characters." ((@ (guix build utils) dump-port) port (current-output-port)) *unspecified*))) =20 +(define (lines+chars port) + ;; Return the number of lines and number of chars read from PORT. + ;; TODO: Also return the number of words. + (let loop ((lines 0) (chars 0)) + (match (read-char port) ; get the next char ready + ((? eof-object?) ;done! + (values lines chars)) + (#\newline ;recurse + (loop (1+ lines) (1+ chars))) + (_ ;recurse + (loop lines (1+ chars)))))) + +(define wc-command-implementation + (lambda files + (let ((files (filter (lambda (file) + (catch 'system-error + (lambda () + (stat file)) + (lambda args + (let ((errno (system-error-errno args))) + (format (current-error-port) "~a: ~a~%" + file (strerror errno)) + #f)))) + files))) + (for-each + (lambda (file) + (let-values (((lines chars) + (call-with-input-file file lines+chars))) + (format #t "~a ~a ~a~%" lines chars file))) + files)))) + +(define wc-l-command-implementation + (lambda files + (let ((files (filter (lambda (file) + (catch 'system-error + (lambda () + (stat file)) + (lambda args + (let ((errno (system-error-errno args))) + (format (current-error-port) "~a: ~a~%" + file (strerror errno)) + #f)))) + files))) + (for-each + (lambda (file) + (let-values (((lines chars) + (call-with-input-file file lines+chars))) + (format #t "~a ~a~%" lines file))) + files)))) + +(define wc-c-command-implementation + (lambda files + (let ((files (filter (lambda (file) + (catch 'system-error + (lambda () + (stat file)) + (lambda args + (let ((errno (system-error-errno args))) + (format (current-error-port) "~a: ~a~%" + file (strerror errno)) + #f)))) + files))) + (for-each + (lambda (file) + (let-values (((lines chars) + (call-with-input-file file lines+chars))) + (format #t "~a ~a~%" chars file))) + files)))) + +(define (wc-commands . args) + (cond ((member "-l" args) `((@@ (guix build bournish) wc-l-command-imple= mentation) ,@(delete "-l" args))) + ((member "-c" args) `((@@ (guix build bournish) wc-c-command-imple= mentation) ,@(delete "-c" args))) + (else `((@@ (guix build bournish) wc-command-implementation) ,@arg= s)))) + (define (help-command . _) (display "\ Hello, this is Bournish, a minimal Bourne-like shell in Guile! @@ -129,7 +205,8 @@ commands such as 'ls' and 'cd'; it lacks globbing, pipe= s---everything.\n")) ("help" ,help-command) ("ls" ,ls-command) ("which" ,which-command) - ("cat" ,cat-command))) + ("cat" ,cat-command) + ("wc" ,wc-commands))) =20 (define (read-bournish port env) "Read a Bournish expression from PORT, and return the corresponding Sche= me --=20 2.8.4 --9jxsPFA5p3P2qPhR-- --SkvwRMAIpAhPCcCJ Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCgAGBQJXX83tAAoJEPTB05F+rO6TwesP/ReFFyjohqaP/4oVUY5NL3VG oAhSgRjK1B7wC5wbN4enoMpHzjIuL6s2XZk/xUYa2junkn8coESFjTfFoDMOHzDh DOFKXiER7GtxF2sk0juasbeDm8tsWSmxA1Q6KJeCPRRmvVsasPOojTqxXO3lXwd0 KewByVh1oEsOow6qTdBSMvUNJsonmo8N5ROCNPzaiwl1AszRT7qLlzWeEvjjZ0Ij lYxgvRJ31YhBU8FQYh3B0mHfnS0kMp1+x29sKxeTGGbmJT98maFiHKkoyTmLtltd +aTnE8aj0wimyb6YwPbQTDSqONLtCog0j728bjyAZ3lL1oC13pWY0igaouXe8YdO y0U/K8C230cokIxuLEOUBZyL+hibEHWqyG1dOpAf4VNGsvM7hKRiQGNFiUH893Mc iTqaxYeJ3JNI1J/GZuTaWkhPuub5T3GKtVb55gwOXq7R7x+nlBSMU1rCHfWb+ELA K1tZPsXdFdIjn7TIavBMXoFskJsEL1b7opuhH2GLkIurBNe0OYthjrmc/ypnW3Mf hmfN15iFBjeJILVXBuZq1CUO/s/yXWStc2VnLj4mp7s0KfZ3Da2Qdzgk5+qg0YtB AOPtw+gCiUsgGIU3nnq1woSVWSr5hTJAdPr3Y0RdjPebzm2IAHBgHg7PNCW+rmBA dtMGMqJMy07TiKC5ziRp =qBGU -----END PGP SIGNATURE----- --SkvwRMAIpAhPCcCJ--