Hacker News new | ask | show | jobs
by throwaway892238 1310 days ago
> I’d love a tool where i can just `cd /tmp/my-hourlong-project` and then `devenv python` to get a python shell that’ll have everything i often use (and probably more)

There's a dozen projects that do this. But it would honestly take you as much time to write a shell script to do it as use some other project to do it.

Like, seriously:

  #!/usr/bin/env sh
  set -eu
  [ "${DEBUG:-0}" = "1" ] && set -x
  MY_TEMPLATE="${MY_TEMPLATE:-$HOME/.my-template.d}"
  _cleanup () { cd ; [ -n "${tmpdir:-}" ] && rm -rf "$tmpdir" ; }
  trap _cleanup EXIT
  tmpdir="$(mktemp -d)"
  cd "$tmpdir"
  cp -a "$MY_TEMPLATE"/* "$MY_TEMPLATE"/.??* . || true
  [ -e ".init.sh" ] && . ./.init.sh
  python
3 comments

I understand this isn't super complex semantically, but even as someone who has used Linux full time on all of my personal desktops/laptops for 10 years now, I don't think I could write shell code like that within an order of magnitude of the time it would take me to google and find a project to do this. Maybe I'm just an outlier, but my perception is that most people don't have instant recall of advanced shell scripting features, if they're even aware of them at all. Off the top of my head:

* I think I remember that `set -e` means to exit early on error, but I don't know enough of the sharp edges to ever feel comfortable using it given how the few times I've tried I inevitably end up having it set for my entire shell session instead of only within the script and not noticed until my shell exited some time later when I made a typo * I recognize `${DEBUG:-0}` as the syntax to use the value of `$DEBUG` if it's set and `0` otherwise, but I can never remember it without googling * I'm guessing `trap _cleanup EXIT` means that `_cleanup` should be run when the script exits, but it's not clear to me whether `EXIT` is some special keyword, and if so what other values would be valid there * I don't think I've ever seen anything close to the left hand side of the `&&` in the cleanup function. Presumably it means to make sure the directory exists before trying to remove it, but I have absolutely no idea why `tmpdir` could possibly be unset or why it would even be a problem if it was even independent of the fact that I would have thought that the `-f` flag to `rm` would make it ignore the directory not existing * is the final `;` in cleanup necessary? If I got a syntax error without it, I don't think it would occur to me that it would be needed * I've never seen `??` in a path before. I'm guessing it means to try to expand `.*` but then not fail if there's nothing? I don't think I would have even thought of the edge case of the expansion not finding anything being a failure

Could I write a script that does maybe 80% of this fairly quickly? Yes. Would the remaining 20% mostly be not thinking of edge cases and then getting frustrated when using it? Probably. Would I give up at this point and just try to find some other tool to handle it for me rather than doing it myself? Almost definitely.

When it's more than 2-3 lines of shell script it's better to just use Python (used to be Perl).
Yeah, my general rule of thumb is that as soon as I need any sort of imperative control flow (like an `if` or a loop, rather than just pipes or `&&`/||`), I stop using shell scripts when able. Sometimes if it's something like a shared build script or something that needs to run in CI across various platforms, it's still necessary to use shell scripting, but if something is just for me, I can use whatever I want, and it won't be a shell script. In the past I've actually preferred Ruby to Python due to easier use of stuff like regexes and inline shell commands (but tend not to define custom classes or anything when doing simple shell helpers), but nowadays I tend to just write things in Rust and compile them to static binaries with musl. In the past I think I've leaned too hard into trying to make things extensible and configurable in case other people would find it more useful that way, and I end up allowing the scope to creep until I eventually burn out and move on to other things. Allowing myself to use the language I want and hardcode things to make it config free and reduce the number of options needed is somewhat liberating.
Now make that template vendor in every dependency reproducibly for Linux and Mac.
oh, for sure. but then take a look at qbasic_forever's sibling comment: by embracing a common shared tool to do this, i also get some nice tools for enumerating templates, with descriptions; i can share my own templates with other nix users without asking them to copy my weird shell scripts, and the reverse; and so on.

don't mistake me for a lazy user in the sense of "doesn't want to write my own code". i'm actually the type of lazy user who prefers to find a project that gets me 80% of the way there, patch it where it falls short, and then upstream my changes so that i don't have to maintain an ever-growing pile of custom patches and one-off shell scripts on my lonesome ;-)