From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Amirouche Boubekki Newsgroups: gmane.lisp.guile.user Subject: Yet another command line DSL Date: Thu, 28 Dec 2017 22:50:56 +0100 Message-ID: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=_6169cffd97bcdd961728d9c7013ef026" X-Trace: blaine.gmane.org 1514497788 30490 195.159.176.226 (28 Dec 2017 21:49:48 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 28 Dec 2017 21:49:48 +0000 (UTC) User-Agent: Roundcube Webmail/1.1.2 To: Guile User Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Thu Dec 28 22:49:43 2017 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eUg3b-0007Wz-B9 for guile-user@m.gmane.org; Thu, 28 Dec 2017 22:49:43 +0100 Original-Received: from localhost ([::1]:40356 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eUg5a-0007LW-1q for guile-user@m.gmane.org; Thu, 28 Dec 2017 16:51:46 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:56323) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eUg4u-0007JT-5q for guile-user@gnu.org; Thu, 28 Dec 2017 16:51:06 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eUg4p-0001CS-5d for guile-user@gnu.org; Thu, 28 Dec 2017 16:51:04 -0500 Original-Received: from relay6-d.mail.gandi.net ([217.70.183.198]:38711) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eUg4o-00018c-NU for guile-user@gnu.org; Thu, 28 Dec 2017 16:50:59 -0500 Original-Received: from webmail.gandi.net (webmail4-d.mgt.gandi.net [10.58.1.144]) (Authenticated sender: amirouche@hypermove.net) by relay6-d.mail.gandi.net (Postfix) with ESMTPA id B64F3FB883 for ; Thu, 28 Dec 2017 22:50:56 +0100 (CET) X-Sender: amirouche@hypermove.net X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.70.183.198 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.org gmane.lisp.guile.user:14388 Archived-At: --=_6169cffd97bcdd961728d9c7013ef026 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8; format=flowed Héllo all, I had to scratch an itch about command line interfaces again. In Python, I use http://docopt.org/ but it's pain (even if less painful that argparse and click) because you have to manually dispatch to the correct function based on a single dictionary to the correct function. Long story short, I made a replacement for that, that should improve the developper experience in guile. Here is an ascii video of the thing: https://asciinema.org/a/VpSS5YTfEuKgAg0J6zwR9ZBxW It's guix related so you might be able to relate to it. At the end of the video the code and attached to this mail. Basically, the idea is to create a nested alist ie. a tree, where leafs are procedures as specification for the cli. It looks like that: (define xote `((package (install ,package-install) (search ,package-search)) (system (init ,system-init) (reconfigure ,system-reconfigure) (generation (switch ,system-generation-switch) (list ,system-generation-list))))) I find it very pleasant to read. When the user type a command like: xote package install guile@2.2.3 The the program will walk the spec and the program arguments at the same time to look for a possible match. When it finds a match it checks whether the user wants help otherwise it executes the command with the rest of the program arguments that are not matched. In the above example ``'("guile@2.2.3")'' is passed as an arugment of the ``package-install'' procedure. What I plan to do next, is to provide a generic function that will look for --optional=arguments in the rest and outputs two lists: - an alist of --optional=arguments or short options like -K - again, the rest of the arguments that were not parsed as short or long options. This simple and generic implementation of arguments will require the developer using this tool to validate the options if he really wants. And will allow him to use his favorite cli tool for short options... The end result is that we have the best of both world, pleasant interface that organize its subcommands by topic and the liberty to use a powerful other framework to parse optional flags. I find this approach clean and sleak. WDYT? --=_6169cffd97bcdd961728d9c7013ef026 Content-Transfer-Encoding: base64 Content-Type: text/plain; name=izicli.scm Content-Disposition: attachment; filename=izicli.scm; size=3229 KGRlZmluZS1tb2R1bGUgKGl6aWNsaSkpCgoodXNlLW1vZHVsZXMgKHNyZmkgc3JmaS0xKSkKCgo7 OzsgaXppY2xpCgooZGVmaW5lIChwYXRoLWRpc3BsYXkgcGF0aCkKICAobGV0IGxvb3AgKChwYXRo IHBhdGgpKQogICAgKHVubGVzcyAobnVsbD8gcGF0aCkKICAgICAgKGRpc3BsYXkgKGNhciBwYXRo KSkKICAgICAgKGRpc3BsYXkgIiAiKQogICAgICAobG9vcCAoY2RyIHBhdGgpKSkpCiAgKGRpc3Bs YXkgI1xuZXdsaW5lKSkKCihkZWZpbmUgKCVzcGVjLWhlbHAgcGF0aCkKICAobGFtYmRhIChzcGVj KQogICAgKGlmIChwcm9jZWR1cmU/IChjYWRyIHNwZWMpKQogICAgICAgIChwYXRoLWRpc3BsYXkg KGFwcGVuZCBwYXRoIChsaXN0IChjYXIgc3BlYykpKSkKICAgICAgICAoZm9yLWVhY2ggKCVzcGVj LWhlbHAgKGFwcGVuZCBwYXRoIChsaXN0IChjYXIgc3BlYykpKSkgKGNkciBzcGVjKSkpKSkKCihk ZWZpbmUgKHNwZWMtaGVscCBuYW1lIHNwZWMpCiAgIkRpc3BsYXkgdGhlIHVzYWdlIG1lc3NhZ2Ug Zm9yIHRoaXMgU1BFQyBmb3IgdGhlIHByb2dyYW0gbmFtZWQgTkFNRSIKICAoZm9ybWF0ICN0ICJV c2FnZTpcblxuIikKICAoZm9yLWVhY2ggKCVzcGVjLWhlbHAgKGxpc3QgbmFtZSkpIHNwZWMpKQoK KGRlZmluZSAoaGVscD8gc3RyaW5nKQogIChvciAoc3RyaW5nPT8gc3RyaW5nICItLWhlbHAiKQog ICAgICAoc3RyaW5nPT8gc3RyaW5nICItaCIpKSkKCihkZWZpbmUgKCVsb29rdXAgc3BlYyBhcmdz KQogIChpZiAoc3RyaW5nPT8gKHN5bWJvbC0+c3RyaW5nIChjYXIgc3BlYykpIChjYXIgYXJncykp CiAgICAgICh2YWx1ZXMgKGNkciBzcGVjKSAoY2RyIGFyZ3MpKQogICAgICAodmFsdWVzICNmICNm KSkpCgooZGVmaW5lIChsb29rdXAgc3BlYyBhcmdzKQogIChsZXQgbG9vcCAoKHNwZWMgc3BlYykp CiAgICAoaWYgKG51bGw/IHNwZWMpCiAgICAgICAgKHZhbHVlcyAjZiAjZikKICAgICAgICAoY2Fs bC13aXRoLXZhbHVlcyAobGFtYmRhICgpICglbG9va3VwIChjYXIgc3BlYykgYXJncykpCiAgICAg ICAgICAobGFtYmRhIChwcm9jZWR1cmUtb3Itc3BlYyBhcmdzKQogICAgICAgICAgICAoY29uZAog ICAgICAgICAgICAgKChhbmQgKG5vdCBwcm9jZWR1cmUtb3Itc3BlYykgKG5vdCBhcmdzKSkKICAg ICAgICAgICAgICAobG9vcCAoY2RyIHNwZWMpKSkKICAgICAgICAgICAgICgocHJvY2VkdXJlPyAo Y2FyIHByb2NlZHVyZS1vci1zcGVjKSkKICAgICAgICAgICAgICAodmFsdWVzIChjYXIgcHJvY2Vk dXJlLW9yLXNwZWMpIGFyZ3MpKQogICAgICAgICAgICAgKGVsc2UgKGxvb2t1cCBwcm9jZWR1cmUt b3Itc3BlYyBhcmdzKSkpKSkpKSkKCgooZGVmaW5lLXB1YmxpYyAoaXppY2xpIG5hbWUgc3BlYykK ICAobGV0ICgoYXJncyAoY2RyIChwcm9ncmFtLWFyZ3VtZW50cykpKSkKICAgIChpZiAob3IgKG51 bGw/IGFyZ3MpIChlcXVhbD8gYXJncyAnKCItLWhlbHAiKSkgKGVxdWFsPyBhcmdzICcoIi1oIikp KQogICAgICAgIChzcGVjLWhlbHAgbmFtZSBzcGVjKQogICAgICAgIChjYWxsLXdpdGgtdmFsdWVz IChsYW1iZGEgKCkgKGxvb2t1cCBzcGVjIGFyZ3MpKQogICAgICAgICAgKGxhbWJkYSAocHJvY2Vk dXJlIGFyZ3MpCiAgICAgICAgICAgIChjb25kCiAgICAgICAgICAgICAoKGFuZCBwcm9jZWR1cmUg KGZpbmQgaGVscD8gYXJncykpCiAgICAgICAgICAgICAgKGRpc3BsYXkgKHByb2NlZHVyZS1kb2N1 bWVudGF0aW9uIHByb2NlZHVyZSkpKQogICAgICAgICAgICAgKChhbmQgcHJvY2VkdXJlIGFyZ3Mp CiAgICAgICAgICAgICAgKHByb2NlZHVyZSBhcmdzKSkKICAgICAgICAgICAgIChlbHNlIChzcGVj LWhlbHAgbmFtZSBzcGVjKSkpKSkpKSkKCgoKCjs7OyBleGFtcGxlCgooZGVmaW5lIChwYWNrYWdl LWluc3RhbGwgYXJncykKICAiVXNhZ2U6CgogIHhvdGUgcGFja2FnZSBpbnN0YWxsIFstZWZdIFBB Q0tBR0UKCiAgLS1leHByZXNzaW9uIC1lICBJbnRlcnByZXQgUEFDS0FHRSBhcyBHdWlsZSBleHBy ZXNzaW9uIGFuZCBpbnN0YWxsCiAgICAgICAgICAgICAgICAgICB0aGUgcmVzdWx0IG9mIGl0cyBl dmFsdWF0aW9uLgoKICAtLWZpbGUgLWYgICAgICAgIEludGVycHJldCBQQUNLQUdFIGFzIGEgZmls ZW5hbWUgYW5kIGluc3RhbGwKICAgICAgICAgICAgICAgICAgIHRoZSBwYWNrYWdlIGJ5IGV2YWx1 YXRpbmcgaXQuCgpJbnN0YWxsIHBhY2thZ2UgaW4geW91ciBjdXJyZW50IGVudmlyb25tZW50IHBy b2xseSB5b3VyIHByb2ZpbGUKIgogIChwayAncGFja2FnZS1pbnN0YWxsIGFyZ3MpKQoKKGRlZmlu ZSAocGFja2FnZS1zZWFyY2ggYXJncykKICAiVXNhZ2U6CgogIHhvdGUgcGFja2FnZSBzZWFyY2gg Wy1yc2FdIFFVRVJZLi4uCgogIC0tcmVnZXggLXIgICAgIEludGVycHJldCBxdWVyeSBhcyBhIHJl Z3VsYXIgZXhwcmVzc2lvbgogIC0tc3lub3BzaXMgLXMgIENvbnNpZGVyIHN5bm9wc2lzIGR1cmlu ZyB0aGUgc2VhcmNoIHRvbwogIC0tYWxsIC1hICAgICAgIENvbnNpZGVyIHN5bm9wc2lzIGFuZCBk ZXNjcmlwdGlvbiBkdXJpbmcgdGhlIHNlYXJjaAoKTG9va3VwIHRoZSBwYWNrYWdlIGluZGV4IGZv ciBwYWNrYWdlIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIFFVRVJZIHdoaWNoCm1pZ2h0IGJlIG11bHRp cGxlIHdvcmRzLgoiCiAgKHBrICdwYWNrYWdlLXNlYXJjaCBhcmdzKSkKCihkZWZpbmUgKHN5c3Rl bS1pbml0IGFyZ3MpCiAgKHBrICdzeXN0ZW0taW5pdCBhcmdzKSkKCihkZWZpbmUgKHN5c3RlbS1y ZWNvbmZpZ3VyZSBhcmcpCiAgKHBrICdzeXN0ZW0tcmVjb25maWd1cmUgYXJncykpCgooZGVmaW5l IChzeXN0ZW0tZ2VuZXJhdGlvbi1zd2l0Y2ggYXJncykKICAocGsgJ3N5c3RlbS1nZW5lcmF0aW9u LXN3aXRjaCBhcmdzKSkKCihkZWZpbmUgKHN5c3RlbS1nZW5lcmF0aW9uLWxpc3QgYXJncykKICAo cGsgJ3N5c3RlbS1nZW5lcmF0aW9uLWxpc3QgYXJncykpCgoKKGRlZmluZSB4b3RlCiAgYCgocGFj a2FnZQogICAgIChpbnN0YWxsICxwYWNrYWdlLWluc3RhbGwpCiAgICAgKHNlYXJjaCAscGFja2Fn ZS1zZWFyY2gpKQogICAgKHN5c3RlbQogICAgIChpbml0ICxzeXN0ZW0taW5pdCkKICAgICAocmVj b25maWd1cmUgLHN5c3RlbS1yZWNvbmZpZ3VyZSkKICAgICAoZ2VuZXJhdGlvbgogICAgICAoc3dp dGNoICxzeXN0ZW0tZ2VuZXJhdGlvbi1zd2l0Y2gpCiAgICAgIChsaXN0ICxzeXN0ZW0tZ2VuZXJh dGlvbi1saXN0KSkpKSkKCgooaXppY2xpICd4b3RlIHhvdGUpCg== --=_6169cffd97bcdd961728d9c7013ef026--