explainshell
explainshell copied to clipboard
Command line version
I would appreciate command line version, so I could write explain tar xzvf archive.tar.gz
or even explain !!
.
I was going to attempt that this weekend. :)
So the first major difficulty I've run into is that explainshell uses lexgrog
for parsing. lexgrog
is part of man-db, an alternative man implementation that's only used on a few Linux distros. Notably, this doesn't include CentOS (though perhaps it will eventually, since it's in Fedora), or any non-Linux Unixes (the BSDs, OS X).
I think you can do the same thing with groff
, given enough work, but the simpler option is to just use whatis
- it seems to give us the same sort of output, albeit only for installed manpages (but that's what we're working off of for a local version, right?).
I think we should start with a client that queries explainshell.com, so it can be as thin as possible and require none of the dependencies needed to run explainshell locally.
So the only thing missing is an API at explainshell.com/api/?command=... that returns the structure exposed by the matcher, who given a command string returns a list of (start-index, end-index, help-text) that we found a matching argument for in the man page.
Then a client simply calls this API and can do cool things like colorize each argument(s) with its help text, like the web interface does with the lines.
Although the dependencies are a bitch, the advantage of doing a purely-client implementation is that it gets the info for the man pages on the system, rather than some arbitrary other system. This irons out problems with version mismatches between Linux distros (the packages on CentOS are significantly older than Ubuntu), implementation mismatches (e.g. bsd ls vs. gnu ls), and miscellaneous locally-installed programs (that aren't global enough to be included in explainshell.com).
That being said, an API-querying thin client is probably easier to create (and certainly to install). I think there's motivation for both existing.
This would be an awesome feature, I can imagine the cross-platform-ness being a bit of a headache though...
A quick and dirty wrapper using command line browser (w3m) to view explainshell pages: https://gist.github.com/weakish/733022#file-explainshell-rc
I agree it could get messy if the man page the site has is different than the one you have locally (perhaps in the future, you could submit your copy to explainshell.com and it will remember it?). But I think over time as more man pages will be added, the problem might become smaller and smaller. I'm not particularly keen on keeping multiple versions of the same program, besides different variants such as gnu/bsd/etc.
The main argument for working with the live site as I see it is that it contains manual corrections that I've done, and in the future I expect these corrections to be done by users too, resulting in more accuracy than that provided by the automatic extractor algorithm.
Having said that, I'll help in any way I can to get a nice fully local explainshell.
As beginner user of linux I would be satisfied with thin client, that queries explainshell.com for quick lookup of simple commands. But sometime I work offline, so I would use standalone version as well.
+1 for api
+1 for API
If the API supports man page submission, then the CLI application could just upload the local manpage if an acceptable one isn't available on the server. By this solution, you have the advantage desired by @xiongchiamiov of providing output for all local manpages, and the advantage desired by @idank for relying on manually-moderated information if it is available. Further, the output of explainshell.com improves, both reducing the need for and streamlining the manpage submission process.
That sounds like a nice solution @drewcrawford. I haven't really started thinking of an API for submitting man pages, that would be quite tricky, but it's definitely something I'd like to do at some point.
@xiongchiamiov In lieu of a RESTful API, one can replicate the backend (mongorestore dump/explainshell
) and hack up a little CLI interface. FWIW, here's an elementary proof-of-concept.
The classification
collection could of course be munged for easier querying.
Here is my command line version perl script https://github.com/idank/explainshell/issues/76 Needs only vanila perl and curl to run
https://github.com/bfr/explainshellcli
Nice, small and simple :).
Here is link for mine https://github.com/troydm/exp
#!/bin/bash
w3m "http://explainshell.com/explain?cmd="`echo $@ | tr ' ' '+'}`
Good solution if you have w3m available. I would maybe dump the page to stdout and cut out the top of the page. Something like this(Maybe replace the sed line with something more flexible, but you get the point):
w3m -dump "http://explainshell.com/explain?cmd="`echo $@ | tr ' ' '+'}` | sed '1,16d'
Thanks for the idea @bfr - I wrapped your approach up a wee bit more to remove some cruft like double blank lines, any lines that mentioned explainshell or had "bullets" in them generated by html. So this doesnt use sed to find the offset, it just removes all the other stuff.
explain_shell
OUT=$(w3m -dump "http://explainshell.com/explain?cmd="`echo $@ | tr ' ' '+'}`)
echo
echo "$OUT"| grep -v explainshell | grep -v • | grep -v "source manpages" | sed '/./,$!d' | cat -s
$ explain_shell ls -ltr
ls(1)
-ltr
list directory contents
-l use a long listing format
-t sort by modification time, newest first
-r, --reverse
reverse order while sorting
@bradparks I made a few changes to your version to make it a little bit faster.
#!/bin/bash
set -euo pipefail
# Here strings are noted to be faster for a small amount of
# data as compared to pipes where the setup cost dominates.
# https://unix.stackexchange.com/a/219806/158139
response=$(w3m -dump "http://explainshell.com/explain?cmd="$(echo $@ | tr ' ' '+'}))
cat -s <(grep -v -e explainshell -e • -e □ -e "source manpages" <<< "$response")
Benchmarks
Before:
explain-shell ls -ltr 0.02s user 0.00s system 1% cpu 1.849 total
After:
explain-shell ls -ltr 0.02s user 0.00s system 1% cpu 1.728 total
Having a command line version would be like an extension to man
itself. In fact it is the better version of man
like as if having man explain '...'
.