6 ms·
Show HN: Lisp Shell
- nerdponx 9y agoAs long as the top-level commands don't have to be manually wrapped in (), I like this idea.
- dexterlagan 9y agoThanks for writing. That's why I made this little shell in the first place: I wanted something quick that worked mostly like sh, but with a Racket inside.
- hawkice 9y agoFun Unix Trivia Time: Touch is supposed to update modified times. That it creates files when they don't exist is only the most common use, not the point of the thing.
- justinhj 9y agoWeird. I learned these two things in the opposite order. I guess my first use of touch was to test out makefiles
- dexterlagan 9y agoThanks! I implemented this just to create blank files, and didn't bother researching correctness. That's exactly the kind of correction I was hoping for when posting to HN. My first post too.
- akkartik 9y agoAnother minor issue: cd without arguments should switch to the home directory rather than display the current directory (as your Readme suggests you do). You already have pwd for displaying the current directory.
- deleted 9y ago[deleted]
- MR4D 9y agoUnless you’re seven directories deep and accidentally hit the <enter> button instead of the <shift> button. In which case, uh, you want the current functionality.
- Cerium 9y agoYou can use "cd -" to go back to the previous directory.
- lyk 9y ago$OLDPWD also holds the previous directory.
- gabcoh 9y agoDoes that work like a stack or does it just swap?
- kbp 9y agoIt only swaps; you can use pushd and popd if you want a stack.
- kazinator 9y agoAlso: - "cd -" has no interaction with the pushd/popd stack except in the sense that it alters the top of the stack (the current working dir). It doesn't swap the two top entries of the directory stack, but swaps the top with an off-stack saved location ($OLDPWD). - "pushd" with no arguments swaps the top two stack entries.
- kazinator 9y agoIf you use "mkdir -", bash will not change into this directory. Not even if you use "cd -- -". "cd ./-" works.
- kazinator 9y agoTo create a blank file, another idiom is "> foo".
- jhbadger 9y agoOh, the update times feature is pretty common, at least among those who use a shared system where "scratch" files are deleted when they are seven days old.
- noobermin 9y agoFunny thing. I work in the computational field where we deal with TBs of data regularly. We are supposed to backup sim outputs to tape asap and using touch to modify modification times to avoid this is explicitly forbidden.
- TeMPOraL 9y agoI suppose this is a similar situation as with `cat' - it's meant to conCATenate stuff, but the most common usage I've seen (and one I've learned) is the idiom of `cat somefile | some-commands'. (Whenever I share a snippet with this idiom, I get told by one of my cow-orkers to stop abusing kittens...)
- klez 9y agoIsn't `some-command < somefile` more idiomatic (also, should spawn one process less)?
- aepiepaey 9y agoYes. See "Useless use of cat" (or "UUOC"). If you prefer to have the command arguments at the end of the line (so it's easier to amend), you can do e.g: < file.txt grep pattern instead of grep pattern file.txt or cat file.txt | grep pattern There are also some related useless uses, like useless use of grep | awk: grep pattern file | awk '{print $3}' which can instead be written as awk '/pattern/ {print $3}' file
- HerrMonnezza 9y agoIt would be nice to see some examples of the syntax, maybe a couple of simple scripts... E.g., the README states that 'cd/' is an alias for '(cd "/")' which seems to imply that one has to wrap every command in '()' and quote every filename... not very practical for a shell!
- dexterlagan 9y agoThanks for the feedback, I will update the description ASAP. I know I need to write a few examples, especially how to handle files. If compiled with pmap, it's possible to do things like: (pmap (lambda (f) (run (+ "[some-command] " f))) (directory-list)) ...and run any binary against all files in the current directory, in parallel. (directory-list) returns a list of files and one can run any Racket function against that list. It's also possible to gather any command output and pipe it back to Racket for processing. I'm working on a more polished build with better docs. I'd like to cover the minimum (like running binaries directly instead of having to use run). I've only begun to think about everything that's needed to bring this to its full potential. I'll also check the other projects I hadn't heard of, maybe some of them are already far better than mine :)
- dexterlagan 9y agoThank you for writing. Agreed, there a need for direction and better documentation. Feedback has been great and this has motivated me to work harder at this. I’d like to have something more standard. I currently use lsh to walk paths and record macros I use in IO tools for production.
- sam-s 9y agoCLASH: CLisp As SHell http://clisp.org/clash.html http://clisp.org/clash.html
- convolvatron 9y agosuprised no one has posted the venerable https://en.wikipedia.org/wiki/Scsh https://en.wikipedia.org/wiki/Scsh
- masukomi 9y agoScsh home page here: https://scsh.net/ https://scsh.net/
- pmoriarty 9y agoThe most memorable thing about Scsh for me is its acknowledgments rant, which starts: "Who should I thank? My so-called "colleagues," who laugh at me behind my back, all the while becoming famous on my work? My worthless graduate students, whose computer skills appear to be limited to downloading bitmaps off of netnews? My parents, who are still waiting for me to quit "fooling around with computers," go to med school, and become a radiologist? My department chairman, a manager who gives one new insight into and sympathy for disgruntled postal workers?" and concludes: "Oh yes, the acknowledgements. I think not. I did it. I did it all, by myself." http://philip.greenspun.com/wtr/dead-trees/acknowledgments.html http://philip.greenspun.com/wtr/dead-trees/acknowledgments.h...
- kbp 9y agoI've never used it as a shell per se, but another little tweak I do sometimes for shell script type things in Lisp is install a read macro like (set-macro-character #\$ #'(lambda (stream char) (declare (ignore char)) `(uiop:getenv ,(symbol-name (read stream))))) This lets you read environment variables like $home, and write to them like ordinary variables, eg (setf $message "hello"). It reads the variable name as a Lisp symbol, so by default it will be upcased; this happens to be convenient for environment variables, but as with any symbols in Lisp, you can escape lowercase characters using either \ before the character or |'s around the whole symbol, or you could change the readtable case, or just preserve case initially in the read macro.
- millettjon 9y agoSee also clojure shell https://github.com/dundalek/closh https://github.com/dundalek/closh
- preek 9y agoFor the Emacs users, there's eshell - a Shell, implemented in Elisp with the common GNU tooling, but also with the option to hook into regular elisp functions. Pretty cool stuff!
- taeric 9y agoWith the major caveat that piping commands together doesn't work that well, eshell has been an amazingly useful feature of emacs for me. Combined with TRAMP support, it makes dealing with remote machines much much more friendly. As an example, "cd 'ssh:firstmachine|ssh:secondmachine:/'" works just like you would anticipate, bounces you through first machine to second machine. All commands from that point are executed as if you were on second machine. You can even run "shell" to drop to a more traditional shell at that point. Even better, "cp someFile ~/" will transmit a file back to my local machine so that I don't have to work with the scp commands that it requires. :)
- josteink 9y ago> Even better, "cp someFile ~/" will transmit a file back to my local machine so that I don't have to work with the scp commands that it requires. Did not know that. That’s a neat trick! Do feel free to share more if you have any :)
- taeric 9y agoDon't really have much else. I do have "M-x g" bound to "magit-status" so that as long as my PWD is in a repository, no matter if it is remote or not, I get my git status buffer. That didn't really require any setup, though. Magit already "does the right thing" if you are on a remote machine. I did have to add a lot to my tramp path. Can't remember why, right off. I just know that it helps find a lot of things that don't make the standard path for some reason.
- preek 9y agoSome time ago, I wrote a small blog post about that Tramp and remote editing files with eshell: http://200ok.ch/posts/edit-remote-files-with-emacs.html http://200ok.ch/posts/edit-remote-files-with-emacs.html
- aetherlord 9y agoRASH, RAcket SHell library and language: https://github.com/willghatch/racket-rash https://github.com/willghatch/racket-rash Note: I am not the author
- dexterlagan 9y agoI started lsh a few weeks before finding out about Rash. I found it too complicated to be used as a replacement for sh, but I might not have read enough about it to make a proper judgment. In the end I wanted to implement something that behaved exactly like I'd expect to.
- willghatch 9y agoI'm late to the party, but I'm the author of Rash. Rash's documentation is terrible and out of date, but I've actually been planning to redo/improve all of the documentation within a week or two. I'm hoping that once I do that it will be much more approachable. Rash tries to allow both Bash style things and more normal Racket to be done with ease and mixed, and a lot of the complexity of Rash has to do with getting those two things to work together, and to allow lots of macro extensibility. But I think you'll find that it's quite powerful and useful... once I make it easier to make sense of. Of course I'm also happy for anyone to make a new shell that they like and want to use themselves. I did it, after all...
- dexterlagan 9y agoHi there, thanks for replying. I’m quite sure Rash is superior to my toy program, tbh I can’t wait to read more about it and check your code. If I have some free time I’ll try to contribute too. Cheers!
- DonaldPShimoda 9y agoI was going to comment about this! The author is a student at my school who studies under Matthew Flatt (so no surprise it's based on Racket). I've worked with him on class projects before and he's not only wicked smart but also a really nice guy.
- lysium 9y agoThis reminds me of my time working with the Scheme Shell scsh! From the readme I don’t quite understand the purpose of lsh, though. Usually, a shell allows you to run programs and manipulate their environment. However, lsh seems to reimplement some commands like find or rm and does not provide operators to manipulate the runtime environment like redirecting output. Maybe you can write in the readme your goal: play with racket, have a shell that accepts racket forms or something different.
- tonyg 9y agoYou might be interested in an experiment of mine, https://github.com/tonyg/racket-something/blob/master/src/something/shell.rkt https://github.com/tonyg/racket-something/blob/master/src/so..., which combines an indentation-based reader with a handler for unbound variables to permit fluid interoperation between Racket procedures and external programs. Here's an example (https://github.com/tonyg/racket-something/blob/master/examples/sh.rkt https://github.com/tonyg/racket-something/blob/master/exampl...): #lang something/shell // Simple demos ls -la $HOME | grep "^d" | fgrep -v "." ls -la | wc -l | read-line |> string-split |> car |> string->number |> \ printf "There are ~a lines here." | sed -e "s: are : seem to be :" (newline) def ps-output pipeline ps -wwwax preserve-header 1 {: grep "racket" } space-separated-columns [string->number] |> csv-expr->table print ps-output def message-box text: whiptail --title "Testing" --ok-button "OK" --msgbox text 8 50 message-box "This is pretty cool." `ls`, `grep`, `whiptail` and so on are unbound Racket variables, and the macros forming part of the `something/shell` dialect replace them with calls to the external programs, sorting out the plumbing, pipes and so on. `read-line`, `car`, `string-split`, etc are ordinary Racket functions from the standard libraries. (EDIT): Here's a screencast of an interactive session with the shell. Very simple, but shows some of the basics: https://asciinema.org/a/83450 https://asciinema.org/a/83450
- dexterlagan 9y agoFantastic! Thanks so much for writing. I'll study all this ASAP.
- jiyinyiyong 9y agoI figured out a way to combine indentation-based syntax with S-expressions too http://text.cirru.org/ http://text.cirru.org/
- jlarocco 9y agoI really like seeing more people use Lisp, and it's neat to see what other people come up with, but I'll stick with Emacs, Slime and occasionally eshell. More often than not it's easiest to just use the Common Lisp functions for creating directories and interacting with the system, but when that doesn't work, I have a function similar to this one in my .sbclrc file: (defun run (cmd) (with-output-to-string (outs) (uiop:run-program cmd :output outs))) At work, I've even created a small Common Lisp library for calling our JSON APIs over HTTPS and running commands on our test clusters using SSH. It's all tightly integrated into Emacs, and I can use it do things like open remote files in my local Emacs.
- gigatexal 9y agoInteresting but one nitpick: always, always, always, in the github readme.md put an example of use so I can see what it’s like before installing.
- xss002 9y ago1
- dexterlagan 9y agoAgreed, I will update the readme ASAP with examples. This is my first post ever, and I didn’t expect such interest. Thanks a lot for writing.
- gigatexal 9y agoKudos for being brave to share. Keep up the good work and thanks for being open to input.
- xss002 9y ago1