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 gMIqHxIcB2BFUgAA0tVLHw (envelope-from ) for ; Tue, 19 Jan 2021 17:51:14 +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 OIXmGhIcB2BEawAA1q6Kng (envelope-from ) for ; Tue, 19 Jan 2021 17:51:14 +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 14C1B9403C5 for ; Tue, 19 Jan 2021 17:51:14 +0000 (UTC) Received: from localhost ([::1]:41802 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l1v9s-0008Io-VJ for larch@yhetil.org; Tue, 19 Jan 2021 12:51:12 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60192) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1l1urK-0002Ad-8I for guix-patches@gnu.org; Tue, 19 Jan 2021 12:32:03 -0500 Received: from debbugs.gnu.org ([209.51.188.43]:39943) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1l1urK-0008Ky-0z for guix-patches@gnu.org; Tue, 19 Jan 2021 12:32:02 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1l1urJ-0001mX-T5 for guix-patches@gnu.org; Tue, 19 Jan 2021 12:32:01 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#45893] [PATCH 0/2] DRAFT: Hint for options. Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 19 Jan 2021 17:32:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 45893 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: zimoun Received: via spool by 45893-submit@debbugs.gnu.org id=B45893.16110775046825 (code B ref 45893); Tue, 19 Jan 2021 17:32:01 +0000 Received: (at 45893) by debbugs.gnu.org; 19 Jan 2021 17:31:44 +0000 Received: from localhost ([127.0.0.1]:51489 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1l1ur2-0001m1-87 for submit@debbugs.gnu.org; Tue, 19 Jan 2021 12:31:44 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38708) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1l1ur0-0001lp-Kx for 45893@debbugs.gnu.org; Tue, 19 Jan 2021 12:31:42 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]:56851) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l1uqr-0008HF-Q5; Tue, 19 Jan 2021 12:31:34 -0500 Received: from [2a01:e0a:1d:7270:af76:b9b:ca24:c465] (port=47960 helo=ribbon) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1l1uql-00049Z-Am; Tue, 19 Jan 2021 12:31:29 -0500 From: Ludovic =?UTF-8?Q?Court=C3=A8s?= References: <865z3xlp2y.fsf@gmail.com> <20210116002634.10401-1-zimon.toutoune@gmail.com> <20210116002634.10401-2-zimon.toutoune@gmail.com> Date: Tue, 19 Jan 2021 18:31:25 +0100 In-Reply-To: <20210116002634.10401-2-zimon.toutoune@gmail.com> (zimoun's message of "Sat, 16 Jan 2021 01:26:33 +0100") Message-ID: <87eeighlzm.fsf_-_@gnu.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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: , Cc: 45893@debbugs.gnu.org Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: -2.85 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=pass (policy=none) header.from=gnu.org; 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-Migadu-Queue-Id: 14C1B9403C5 X-Spam-Score: -2.85 X-Migadu-Scanner: scn0.migadu.com X-TUID: /YldhRE/VHwt zimoun skribis: > * guix/utils.scm (levenshtein-distance): New procedure. > (string-closest): New procedure. > * guix/scripts.scm (option-hint): New procedure. > (parse-command-line): Add 'option-hint'. Yay! > +(define (option-hint guess options) > + "Return the closest long-name from name based on Levenshtein distance." > + (define (options->long-names options) > + (fold (lambda (name res) > + (match name > + ((? char?) res) > + ((? string?) (cons name res)))) > + '() > + (fold append '() (map option-names options)))) I think this can be simplified a bit: options->long-names =3D (filter string? (append-map option-names options)) > + (fold (lambda (name res) > + (if (string-null? res) > + (string-append "@code{" name "}") > + (string-append "@code{" name "}, " res))) > + "" > + (string-closest guess (options->long-names options)))) > + > (define (args-fold* args options unrecognized-option-proc operand-proc .= seeds) > "A wrapper on top of `args-fold' that does proper user-facing error > reporting." > @@ -149,6 +167,9 @@ parameter of 'args-fold'." > ;; Actual parsing takes place here. > (apply args-fold* args options > (lambda (opt name arg . rest) > + (display-hint > + (format #f (G_ "Do you mean ~a?~%") > + (option-hint name options))) > (leave (G_ "~A: unrecognized option~%") name)) > argument-handler > seeds)) [...] > +(define (levenshtein-distance s1 s2) > + "Compute the Levenshtein distance between two strings." Maybe call it =E2=80=98string-distance=E2=80=99? > + ;; Naive implemenation > + (define loop > + (memoize > + (lambda (as bt) Instead of (memoize (lambda =E2=80=A6)), you can write: (mlambda (str1 str2) =E2=80=A6) > + (match as > + ('() (length bt)) The pattern for the empty list is (), not '(). How about making this addition to (guix utils) a commit of its own, and to add a small test in tests/utils.scm? > +(define (string-closest trial tests) > + "Return the list from TESTS the closest from the string TRIAL based on > +Levenshtein distance." Maybe something like: =E2=80=9CReturn the string from TESTS that is the clo= sest from TRIAL, according to 'string-distance'.=E2=80=9D > + (match (fold (lambda (test res) > + (let ((dist (levenshtein-distance trial test))) > + (match res > + ((val lst) > + (if (< dist val) > + (list dist (list test)) > + (if (=3D dist val) > + (list dist (cons test lst)) > + res))) > + (_ (list dist (list test)))))) > + '() > + tests) > + ((_ rest ...) (match rest ((head _ ...) head))))) You can simplify this a bit by using =E2=80=98fold2=E2=80=99, which allows = you to pass two seeds instead of one: (fold2 (lambda (test closest shortest-distance) =E2=80=A6) "" +inf.0 tests) It returns two values and the first one is the string. Ludo=E2=80=99.