5 ms·
So what do you use for shell scripting?
by cutler 4y ago
So what do you use for shell scripting?
- cercatrova 4y agoI like using Nim or Rust, or TypeScript, depends on the script. If it's just a few lines, sure I'll write it in bash, but if it gets a little larger, I convert it into a real programming language.
- dotancohen 4y agoRust as a replacement for a bash script? My bash scripts are often edited, I could not imagine using a compiled language where I would have to store the source as a separate file from the executable, then compile it each time. I'd love to know your more specific use cases, if you don't mind. I'm always happy to learn something new. Could you share some Rust that most people would script in Bash as an example? What's your build and deploy (to ~/.local/bin I presume) strategy?
- cercatrova 4y ago> where I would have to store the source as a separate file from the executable, then compile it each time > What's your build and deploy (to ~/.local/bin I presume) strategy? You can run scripts as you would with bash, you don't have to manually build and run the executable. For example, `cargo run (inside the script source folder)` and `sh script.sh` do basically the same thing, end user wise. `nim compile --run script.nim` is similar in that the language compiler will automatically compile and run it together. > Could you share some Rust that most people would script in Bash as an example? I was creating dotfiles the other day and I didn't want to use some dotfile manager program as I had some specific steps I wanted to follow, so I started it as a bash script. Well, it got kind of annoying so I made it into a Rust script with some nice features like interactive prompts, text coloring, etc with libraries like `clap`. You can do this in bash of course, but the Rust version was more ergonomic. When I need to run the script, I just did `cargo run` and it worked great.
- dotancohen 4y agoI see, but then your scripts are not nice compact commands. For instance, my most-used bash script takes a file as input and opens either VIM or Emacs depending on whether the file is a .md or .org (simplified example). I run it like so: $ n foo.org I can edit ~/.local/bin/n and update the file, and use it immediately. I actually have my whole ~/.local/bin in version control. Having to type out e.g. $ nim compile --run n foo.org ...would make the whole experience far less fluent. I probably would never use it. I'm asking because I'd love to rewrite this script in e.g. Rust, but I don't see any good way to deploy it to ~/.local/bin/n.
- cercatrova 4y agoJust alias the command in your .bashrc? e.g. `alias n="nim compile --run n"`. I'm not sure what the issue is with longer commands because the benefits of writing in a strongly statically typed language definitely outweigh a few extra characters to type, which you don't even need to do with aliases.
- cb321 4y agoFor what it's worth, you need only type "nim r n". If "n.nim" is marked executable and begins with "#!/usr/bin/nim r" then you also need only type "n.nim".
- firesloth 4y agoFor nim, you could use something like nimcr (https://nimble.directory/pkg/nimcr https://nimble.directory/pkg/nimcr). You put a shebang in your script `#!/usr/bin/env nimcr` and then call it like a normal script. eg: $ code script.nim #!/usr/bin/env nimcr echo "hello world" $ ./script.nim hello world edit: There's also the possibility of using nimscript, using nim e. It works similarly but you'd change the shebang line to something like #!/usr/bin/env nim e --hints:off
- firesloth 4y agoActually another way to do nimscript is to make a config.nims file with tasks in it. eg: In config.nims: switch("hints", "off") task hello, "say hello world": echo "hello world" In bash: $ nim hello hello world
- paldepind2 4y agoBut TypeScript doesn’t have ADTs which you stated was a hard requirement. It has some other features that can achieve similar things though, so maybe that’s good enough?
- mind-blight 4y agoDiscriminated unions aren't quite as nice, but they're pretty close.
- piaste 4y agoKinda nitpicky. Sure ADTs are a pattern in Typescript rather than a first-class entity, but they're an extremely well-supported pattern, exhaustiveness checking and all. type ADT = | { case : 'a', a : Number } | { case : 'b', b : string } function f (c : ADT) { switch(c.case) { case 'a' : return c.a case 'b' : return Number.parseInt(c.b) // case 'c' : return 0 // compile error // case 'b' : return c.a // also compile error } }