Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
SD: My script directory (github.com/ianthehenry)
122 points by sph on Dec 31, 2022 | hide | past | favorite | 47 comments


Nice tool. But I would think about using traditional “--“ for passing conflicting arguments to a script instead of really-really approach. Double dash means stop processing args and pass/use them as is. This way you can e.g. rm a file named “-f” or echo a string “-n”.

  rm -- -f
  echo -- -n


Yeah, the problem is that I am very likely to write a script that takes `--` as an argument, and I don't want to have to write `-- --` when I call it. I am very unlikely to write a script that takes `--really` as an argument, so it's a little less annoying.


My bad, I failed to think about it in a context of a personal launcher… now that you said it, it sounds much more reasonable than --!


+1 to this. I've been using it for a while.

It doesn't do a great deal, the magic is that it removes just enough hassle from the shell scripting process that I write far more than I used to.

- I don't have to worry about accidentally giving my scripts names that collide with other things on my computer, because they all live in the sd namespace. It's kind of like the Vim leader key, but for the shell.

- I don't worry about forgetting about my scripts later on, because I can browse them with tab completion.

- I'm motivated to write a 1-line documentation comment explaining wtf the script does, again because the comment gets picked up by the tab-completion and displayed as description.

Now I have a growing collection of little scripts organized with sd. Many of them are trivial one-liners. Some of them are even just stuff I could accomplish with bash syntax but kept forgetting how to do because punctuation is harder to remember than words. Previously I would write these things but then forget about them later on, negating the point. And the worry of forgetting made me not write scripts in the first place. I don't have to worry about forgetting to write `set -euo pipefail` because it does it for me.


I used to do something similar a long time ago, but over time calling everything exclusively through a starter-script turned out to be fragile and annoying in some situations. So at some point I moved everything back into $BIN and now organize all scripts just with prefixes and dedicated starters.

Main advantage of the starter-scripts is that I can use file-extensions for my scripts and have dedicated entry-points for each functionality. I just let the starters figure out which script to call. Additionally if I call the starter without a scriptname, It delivers me a selector for selecting a script to call, optimized for the context. Normally I use rofi to select a script.

And today I even have starters which take into action which window is active, and deliver me matching scripts for context-aware work. The improvement on productivity with this quite simple setup is insane. I used to have launcher-apps like launchy or alfred & quicksilver on MacOS. But they were so inflexible that they can't compare for me to my customized rofi-experience. Really insane how much worth such simplicity can have.


Do you have these scripts anywhere for viewing? I’m interested in viewing them


No, not at the moment. I would need to clean it up to make it reproducible for others. And also check for security and privacy-relevant parts.


I love the idea and I'll try it out, but a heads up in case the author is around: the name sd clashes with another tool [0], which works as an alternative to sed.

I use that one pretty often, so maybe my first managed script will be one which symlinks binaries :)

[0] https://github.com/chmln/sd


You could try using sad instead which has interactive diff confirm. https://github.com/ms-jpq/sad


Yeah :( https://github.com/ianthehenry/sd/issues/9

The trouble is `sd` is just so easy to type on a qwerty keyboard, and it's such a nice mnemonic for "script directory." I've thought about renaming it, but I can't think of anything I like nearly as much.


This reminds me on some weird linux/mac/unix tool people used in a project. It changed the PATH (or more generally the ENV) based on the current working directory, so they could easily manipulate the developers shell from the project git repo. I found this terrible and fascinating at the same time. I don't remember the name of this tool. Who does?



Direnv is such a great tool. I use it in all of my projects.


Seconded, I love it and I honestly don't know how people deal with configuration without it.

The applications I develop all run in Docker or Podman, with configuration passed as environment variables. Direnv is excellent in dev mode to configure local env vars such as database credentials that only apply to a specific project, and you will have to approve any change before they take effect, in case you made the mistake of committing it. To avoid that, I just have `.envrc` listed in my ~/.gitignore


On its own, it's nice for development for setting stuff like DB URIs, activating Python virtual environments, etc.

But I find direnv indispensable for how it combines with nix (probably asdf would be good enough too) for "project specific tools". -- The convenience here is not having to remember to install tools system wide in order to work on some repository.


Does direnv have an advantage over `nix develop` in that regard?


Yup:

direnv hooks into the shell, so that it adjusts the environment variables / PATH when you `cd` into the directory. (Well, you do need to run `direnv allow` to indicate you trust the `.envrc` file).

(Also, `nix develop` drops you into a bash shell, which is annoying coming from fish).


direnv has integration with old nix shell as well as new nix develop. It also happens to have lot more editor integration that can utilize nix indirectly instead of not having access to nix at all.



He already seems to be using Zsh. So, as others have said, just putting things `~/bin/blog/` & etc. would (mostly) do the trick..(maybe with an almost trivial "new" script to create, shebang & chmod).

As unyet mentioned, if you `setopt PATH_DIRS` then you can just say `blog/publish`.

This used to be a very popular namespacing device as in `/usr/bin/mh/inc` for the MH Mail Handling system where people would just type `mh/inc`, but POSIX dropped that behavior for `$PATH` search in the "standard" shell (whose standardization had a less interactive focus).


This has come up before, so I probably should mention it in the README at this point. There are some differences:

The main feature of sd is the command descriptions in autocomplete. PATH_DIRS doesn't include these, so it's hard to compare them.

At least by default, PATH_DIRS won't autocomplete nested directories. If you have blog/publish, it works fine. If you have blog/admin/ssl, you won't get autocompletion for admin. You can still run blog/admin/ssl with PATH_DIRS, but the subcommands are not discoverable anymore. (I'd love to know if there's an option to change this!)

Finally, a trivial new script would be very easy to write, but giving it autocomplete for existing directories `new blog/admin/whatever` would not be trivial. And an "edit" script (which I use more often than new) would be very annoying without the same autocomplete. And if you write those, then, well, you've basically just implemented sd with SD_ROOT=$HOME/bin :)


Fair enough. I agree that the README treating autocomplete descriptions as a "but, wait also!" does not make it seem like "the main feature". Projects often evolve faster than documentation. It happens. :) Seems this is more all about autocomplete (which can be..pretty ornate in Zsh) than dispatch..

I don't know of a `setopt` to fix completion for the blog/admin/ssl case, but Zsh mailing list guys are very helpful. With absolute paths Zsh is pretty multi-component smart..E.g. "/u/lo/bi<TAB>" can expand to "/usr/local/bin/" (with my mix of setopts anyway, assuming the expansion is unique). So, could just be more bug than intention.

--

FWIW, the distinctions you drew highlighted (to me) "second class" support for NON-`sd` commands Re: this summary line. I expect this is the sort of thing a daily `sd` user might notice anon, but I did not see any issue on your github repo about this. I suspect it would not be hard to address.

To be more concrete, the standard man format has a one-liner-ish summary of what regular commands are used by the old `man -k/apropos` system. You just need a general `extracted-summaries-from-man-or-scripts` data file (updated in cron/etc.). Once system & `sd` summaries are merged, search of that file(s) (even by just grep) is a more complete path to discovery. :) The TAB completion discovery you like is really just prefix-only search.

You might be able to use this same data file to make `sd` a master meta-command that could dispatch not just to your own scripts but to anything both in $PATH and with a 1-line summary in its man page (or some similar rules). I might imagine typing sd prefix<TAB><more-to-isolate>--help<ENTER> becoming common.

And, of course, just generating a barely populated man page with just titles and your summary line and installing that into the regular man-system and using apropos is another idea for non-TAB-oriented discovery/search/recall.

Well.. /Brainstorming for now and Happy New Year! :)


I've found the script runner "just" to be worth using. https://github.com/casey/just

just (at a glance) is like a Makefile, but with some nice UX improvements that make it worth using. e.g. with `just --choose`, it runs fzf against the targets.


Just is good stuff for project directories, never tried to use it like the author describes `sd`


I've clearly missed something. How is this any better than just executing a script in a well organized directory? Seems like I lose tab completion without significant benefits.


sd actually has tab completion and it was one of the reasons the author made it

He explains it on his blog: https://ianthehenry.com/posts/sd-my-script-directory/


I love this description of the impact of the tool:

> Being able to type sd new foo command instead of vim ~/bin/command, typing the shebang, trying to run it, realizing I forgot to make it executable, running it again… it’s made my life slightly better. And because it’s so easy to save snippets for later, I find that I’m much more likely to do it – and a lot less likely to find myself combing through ctrl-r a few months later.

> Otherwise, you know, it’s not lifechanging. It won’t help you to appreciate the smaller beauties all around you. You’ll still wake up feeling groggy.


Ah gotcha. That info is in the repo, just didn't get through my head the first time. Didn't know tab completion could be used like that.


This is a definite enhancement over my existing “big pile o scripts” directory. I plan to dig in later and find out if different scripts can run in different pyenv virtualenvs.


If you're into this kinda thing then then you might be interested in my take on improving over a "big pile o scripts" (and repos).

https://github.com/davvid/garden

Garden is a multi-repo powertool for running custom commands and mashing random shell scripts and loosely-coupled repos into a version-controllable config file. If you're weird like me you might like it.


> Don't you hate it when you can't find the scripts you need, when you need it? Well now there's a better way!

It's a good start, and there are definitely some ideas worth stealing there, but I don't think it really solves the core problem. Not when you have scripts that cross problem domains, or the name isn't very intention revealing, or you've just got hundreds of them.

The real key to solving this, is searchable documentation. Yeah, I know. No-one wants to write docs. But it doesn't have to be hard, and it doesn't have to be much. It just has to be enough that when next have a problem that involves say "image manipulation" you can ask your system for things that handle "images" and have it list them.

That's why I wrote TooLoo:

https://tooloo.dev

TooLoo's not for everyone, but if you've been building up your own library of useful utilities then I'd _strongly_ recommend you consider the value you'll gain from the combination of a little bit of documentation + Full Text Search. Full Text search is, I think, really important. I don't want to not find something because I searched for "image" instead of "images" or vice versa. You need a search engine that'll deal with stemming.

In documenting my tools for TooLoo I found many useful things that I'd written and completely forgotten about, and others that I'd duplicated because I'd forgotten I already had something like that. Now I always start by asking TooLoo if I have something relevant, or how to use that relevant thing I haven't touched in 3 years.

Anyway. If this type of stuff sounds interesting to you check out TooLoo. If TooLoo's not right for you, make something cool for yourself that uses Full Text Search to find the stuff you need. Most databases have it built in these days: SQLite, PostgreSQL, MySQL, MongoDB, etc.


This seems to solve problems i never ran into.


"Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something."

https://news.ycombinator.com/newsguidelines.html


And you post answers a question I would never have asked, "I wonder if this will be useful to DrinkWater".

Different people's behaviour patterns and needs are different, not everything is useful to everyone so don't expect everything to be useful to you. It isn't something I'll ever use, but I can see why it might be a benefit to some (the author describes the intended utility pretty well).


This still doesn't help me give my scripts meaningful names ;)

I tend to use rg on my ~/bin and search for a string I hopefully put in the script in a comment somewhere. Maybe sd could add an apropos feature.


One idea would be to have a script that runs every one of them with --help and indexes the result


It could also index comments at the top of the file, for those of us not diligent enough to add a --help flag


I just have template for all the boilerplate around cmdline handling for whatever I write in.


You think random scripts I just made to put in ~/bin support --help?


You haven't put anything else useful for info in it either so no difference for you


From what I can tell, sd has a feature that reads a comment or something from your scripts and displays them in the tab completion. So 'sd <tab>' would show a summary of commands and apropos.


I'm not sure I would use this myself [primarily that my 'workflow' doesn't really work with this being in ~/bin and all], but you have some really nice ideas here that I didn't think of before. When I get time later, I'm going to poke around and see how you put it all together. I bet I could copy some things here for some of my other 'projects'.


I don't know how you did it but the tone of your README.md forced my brain to read it in a Sal Goodman voice! Love it! :D


How about a tool that does the opposite of Copilot: given a bunch of scripts, it generates a human readable synopsis, and perhaps even a usage summary and some keywords for each script. Then you can easily search for them using grep.


Love this idea. I've been hacking together something similar, only with one big-ass rc file. This might be better.


plan 9 typically has a single /bin directory (a union mount of various others), and relative path resolution works with slashes, so given a script /bin/aux/wham, it can be run with

% aux/wham


any consideration to take the unique match into account?

So instead of writing "sd foo bar" you could write "sd f b" if foo and bar are unique?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: