1. 3

    Interesting. Looking forward to seeing what @andyc has to say about this one, although I suspect it’s pretty much already been said at http://www.oilshell.org . Do you suppose the author (Terry Jones) is aware of https://xon.sh ? It’s not mentioned in the README.

    1. 3

      There’s an issue on the bug tracker: https://github.com/terrycojones/daudin/issues/6

      1. 1

        I used Xonsh for a while, until I ran into some pretty annoying performance issues (that was ~2 years ago). I did love the blending of Python and shell, but remember it lead to some awkward syntactic edge cases. I eventually settled for Fish, but continue to write my scripts in Bash (and the amazing ShellCheck) – the pipe remains a very powerful abstraction, so maybe Daudin would hit that sweet spot, where we get first-class integration with the command-line environment and a good language. It seems to me it has more potential as a shell-scripting replacement than a real REPL shell.

        1. 1

          Hi Sebastien. I’m also a fish user :-) I’m trying to avoid awkward edge cases in daudin, but sometimes it’s not clear how best to do things. E.g., if you run ls --color=auto in daudin you get nice coloured output because it runs in a pseudo-tty and you probably want to keep the output for later pipeline usage. But if you run git status you also want the coloured output in your terminal but do you actually want to keep the output to use in a pipeline. Worse, what if you run (say) vim from inside daudin? It works fine, but what should be in the output / pipeline from that command? I could “fix” that at the expense of not allowing one to continue a pipeline by starting the subsequent line with a pipe.

          Anyway, I tried to stay as close to pure Python as I could manage, with the explicit goal of minimizing edge cases. The special % commands can all be done with a very small (usually one line) piece of Python, so they’re just syntactic sugar.

          There are certainly rough edges in daudin with respect to exception handling. Hopefully I’ll improve that as issues arise.

          BTW, tonight I made some changes so that you can run a daudin script by putting commands in a file (#!/usr/bin/env daudin works too).

          Thanks for the comment. I don’t know where this is all going, and I didn’t think much before writing it. It’s just a fun project. But I think it’s getting to the point where I can consider actually using it (I now also have a dynamic and coloured prompt). But I’ll certainly miss the awesome predictive powers of fish…

        2. 1

          Hi @minimax. As @ngoldbaum says below, I didn’t know about xonsh. I’ve since had a little look at it, but only a bit. I should make time to read it more carefully. If I’d known about it I might not have started. But OTOH, I figured I could make something work in one evening and I love coding, so…… Implementing daudin was really more of an exercise in thinking than anything else - provoked by comments from my Lisp-loving friend.

        1. 1

          Pretty cool! How do you mix things? Do you do AST edit of Python or do you wrap the command utilities in a python wrapper function like Plumbum ?

          1. 1

            Hi. Thanks for the Plumbum pointer - I’d not heard of it. It looks nice and well thought out. My approach isn’t well thought out at all! I just split the command line on the pipe symbol (as long as it’s not preceded by a backslash) and try to deal with each piece: special commands, eval, exec, shell. It’s very basic. Maybe I’ll have to parse the command line at some point, but I’d like to avoid that if possible. The main downside (that I’m aware of) to the daudin approach is that you can wind up speculatively passing rubbish (e.g., Python commands that are syntactically incorrect) to the shell. Normally that just results in a shell complaint too, but one can imagine a scenario wherein you try to type a Python command to do something innocuous but you somehow get it wrong and it’s passed to the shell where it does something bad. I think that would be difficult / unlikely in practice, but it shouldn’t be hard to concoct a pathological example.

          1. 1
            >>> from math import pi
            >>> pi
            3.141592653589793
            

            Something doesn’t seem quite right when variables are evaluated as-is without any sigil prefix (e.g. $pi). Seems like you would often accidentally reference variables and methods. If I have an executable in my $PATH at /usr/bin/pi, what happens (or unexpectedly doesn’t happen)?

            1. 3

              Well, you just monkeypatched your pi (-:

              >>> from math import pi as ls
              >>> ls
              3.141592653589793
              >>>
              
              1. 6

                To take it a step further, we see what gives me an uneasy feelings about these kinds of shells:

                >>> which ls
                /nix/store/x6a3r9rsazlildaxzqay73scy6nv1inz-coreutils-8.31/bin/ls
                >>> ls
                3.141592653589793
                

                (Not disparaging the idea; it’s interesting—I can just never keep myself using these things because “I need which to not lie to me”, etc.)

                1. 2

                  For what it’s worth, the ambiguity isn’t necessarily an inherent problem with shells as DSLs in a general-purpose language. In Rash (my shell in Racket) there are different pipeline operators that are explicit about taking shell commands or functions – eg. the | operator takes on its right-hand-side a shell command (or user-defined alias), while |> and |>> take Racket functions. Of course they’re all just macros, so you can define custom ones with any behavior, including convenient but ambiguous versions.

                  1. 2

                    Yes :-) I guess this to some extent is a matter of taste. In the case of daudin it’s just inheriting the behaviour of Python and I wanted to keep as close to the language as possible (the %cd etc commands make me cringe a bit, but they’re all easily accessible via Python). You can do all sorts of alarming things in Python if you want or need to, or unintentionally (e.g., if you use id as a variable name you lose access to the built-in function of that name). Strictly speaking it’s a potential minefield, but in practice (at least for me, and I think that goes for many/most professional Python programmers) it’s not an issue. I guess one could replace things like sys with versions that raise exceptions if you try to modify their attributes, but AFAIK no one does. BTW, I have a similar feeling about Python’s numpy package. It feels totally cryptic and magic because it hides a lot of functionality behind what looks like regular Python operators. In general I like Python’s approach to “magic” methods, but it always feels to me like numpy has pushed it too far (but I’m an irregular user of numpy and suppose I would quickly have a different feeling if I used it more).

                    Sorry for so many words!