Huffshell: You probably type too much.
paulmckellar.com
paulmckellar.com
Rather, it's the evolutionary end-point of some 40+ years of continuous improvement in issuing and processing text-based information streams (both commands and outputs), in a very powerful, highly flexible, extremely adaptable manner.
The age of "Oh, Linux, that's like DOS" are far beyond us. But it bears pointing out that this is much like comparing a pogo stick to an F-22 / Boeing 777 / Mercedes E-class. Yeah, the both get you places. How, how much, at what speed, and in what style ... differ.
Well, more like comparing an early horse drawn carriage to the latter three. A pogo stick has always been a toy - never designed to get work done, however inefficiently. Primitive command lines were still attempts at letting you get work done, they just weren't as good as what we have now (or, in some cases and for some purposes, contemporary graphical alternatives).
One of the first selling points for Linux when I first started exploring it a decade and a half ago was that while some of the internals were a tad crufty, the userland (much of it, admittedly, GNU) didn't suck, and didn't suck in a much bigger way than stock commercial proprietary unices did suck.
Pogo stick or oxcart, the point is that many such tools were, or are now, pretty much intentionally crippled.
DOS / cmd.exe, last I checked, didn't have true pipes, true shell expansion, or true readline capabilities (unless it's now GPLd, which I very much doubt). It does have some history and tab completion (though that last works weirdly IMO).
By shell expansion: expansion of wildcard globs by the shell, and not by specific utilities. Piping -- I forget the specifics, but it's always seemed hit or miss, mostly miss. Readline: see readline(3).
DOS was primitive but the things you mentioned worked, even if they were a simulation. The end user was unaware, unless they needed real OS capabilites. In which case, why were they using DOS?
Cmd has a lot of improvements most people are not aware of because they were off by default. Still they refused to do further improvement necessary to make it very useful. There is a 3rd party shell called 4NT that is/was a compatible and very powerful replacement.
Which doesn't happen in any Bourne-compliant shell, as it's the shell which expands the wildcard, not the app (an unexpanded or escaped wildcard character can of course be passed to an executable).
One trick I've learned, if you want to make sure you get the benefit of this sort of approach, is to ensure that the new alias is not just possible, but mandatory. If you map "git commit" to something, you should make it no longer possible to type "git commit" instead of your new alias, and doing so should pop up the correction. This can also be used to move keys around; turn your Caps Lock into a Control key, you'll never use it, but if you unmap the left Control key at the same time, you'll find you've adjusted in about 5 uncomfortable minutes. It's fast enough to be worth experimenting with.
I'm now using this strategy whenever I want to change something like a common command or key binding--essentially anything that is a habit I don't have to think about.
Another thing to note is that it really helps if you come up with the alias or new key combination yourself. I find it takes almost no effort to memorize a key binding I choose myself as opposed to remembering a new one that comes with the tool itself.
" disable arrow keys
nnoremap <Up> <nop>
nnoremap <Down> <nop>
nnoremap <Left> <nop>
nnoremap <Right> <nop>A bunch of people I know do use the arrow keys to move around, and it's quite a loss. You don't gain that much just by being on the home row, of course, but there is some gain. However, the real win comes when you start using higher-level movement commands and moving by word/line/paragraph/expression/whatever. People used to the arrow keys will not be able to take advantage of these nice commands nearly as easily.
Aliases are not expanded when the shell is not interactive,
unless the expand_aliases shell option is set using shopt (see
the description of shopt under SHELL BUILTIN COMMANDS below).The single command to actually count this occurrences required way more typing.
If you have to do it twice, think it over a bit.
If you have to do it a third time, automate it.
I am lazy enough that I have aliases setup to change to directories I frequently use. I know people who have gone far beyond anything I have done and looking over their shoulder when they are at the shell will show a highly custom environment with dozens of custom scripts that automate all sorts of multi-step commands.
I even know a few people who have used most of the alphabet to create single letter scripts. That is efficient!
e.g. https://github.com/rupa/z
I very, very rarely type cd by hand anymore, mostly just use z and popd
Not that I'm against aliases - even minor time savers are indeed worth it - I just wouldn't call it "too much". I bet that a lot of people wouldn't care that much.
In addition, if you're at a terminal on a new server, or someone else's station, all those aliases will be gone.
For me, that means any special aliases or scripts had better be awesome enough to convince someone else to use them... Or infrequent enough that I can't be bothered to remember the whole command. Or just so useful that it's worth overriding the above.
Shortening a 3-letter command into a 1-letter command is not going to fit into the above. Especially when I will have typed 'git' before I remember that I can just type 'g' instead, since I touch-type without looking. It just flows out.
When I log into a new machine I still need to be able to find my way around, I still need to be able to edit files, I still need to be able to run various different commands. These can even be completely different shells or different versions of vi (nvi on FBSD for example, vim without python support on another system and so on).
Yes, my workstation has my vim customisations, but it only has the bare needed ones the rest are stock. Even on a vim without any of the scripts I have I would be proficient and I wouldn't miss a beat. Same thing for the shell, typing commands in full means I don't have to worry about muscle memory.
ll for example for ls -la is nice and all, but it isn't available on most of the machines I administer so I end up typing out ls -la anyway. That has become muscle memory for me now, and I am not worried about trying to change that.
I think that would skew the results a bit if so.
You're right that it does not accurately describe his typing, but it does describe which commands he uses most... which is about half as good.
* Add call stub to Foo, add calls to the stub where needed
* Beginnings of implementation, seems really friggin slow right now.
* Ok, back to square one, need calls to X, Y and Z, can be chained together, wrap behind the call we actually need.
* Final implementation
Which I then may leave comments in the code about the obvious approach that didn't work, or why it is the way it is. I then squash this into two commits, first one covering the implementation added to Foo with an appropriate descriptive commit message and a second commit after it that actually uses the new implementation.Most of the incomplete commits aren't necessary, but we only develop on topic branches and I have a desktop I use at work and a laptop that travels to and from work with me (in case of deciding to work at a coffeeshop, or want to kick back, etc.). The ability to push not-yet-done work to my topic branch makes it available to either computer and the committing when halfway through because it's time to not be at the desk can easily be fixed with squashed commits.
$ git commit -m "It is possible
to write a multiline
commit message
using the -m flag."
Just hit RET or C-j while you have an open quote and you can send newlines to your heart's content.I'm fond of speaking tersely.
[1] rudimentary script: https://github.com/decklin/bin/blob/master/hprune (haven't bothered to add real option parsing or make it efficient; for shell histories of thousands of lines you probably want to up the search depth to something in the hundreds)
If I get to the point where I want to play with this, I'll probably fork it and propose some changes back. It also strongly suggests that I should blow away my history because there's some unusual values reported because of my work.
sf = tcstop && mvp stretch-base,stretch-app && tcs
tcstop = ~/tomcat6/bin/catalina.sh stop
mvp = mvn package -projects
tcs = cl && tcstart && sti
cl = cleard; cleari; cleare; cleart
cleard = find /cygdrive/c/var/log/tomcat6/*.debug -exec truncate -s 0 {} \;
cleari = find /cygdrive/c/var/log/tomcat6/*.info -exec truncate -s 0 {} \;
cleare = find /cygdrive/c/var/log/tomcat6/*.err -exec truncate -s 0 {} \;
cleart = find /home/sthomas/tomcat6/logs/catalina.out -exec truncate -s 0 {} \;
tcstart = ~/tomcat6/bin/catalina.sh start
sti = tail -f /cygdrive/c/var/log/tomcat6/*.info ~/tomcat6/logs/catalina.outPersonally, I like to leave my setup as stock as possible, so I can still be productive regardless of whose computer I happen to be using.
Now, I'm aware that there are different usage scenarios. A typical developer only ever works on a handful of systems at the same time period - which makes handling your personal set of scripts a viable option. Administrators are an entirely different beast.
But there is a point about optimizing typing. If you're just going to replace "git" with "g", you'll save two characters. You're probably not quite down to a third of the time, but there will be a measurable difference. But given that there's some overlap with other actions (e.g. you might already be pondering your commit message), the measured productivity increase will probably be pretty small.
In cases like that, it's probably better to look at the whole workflow, so you're not just saving time at the micro level. Save/unify several steps of the whole procedure (e.g. combine save-commit in your text editor).
And then consider that by reading this thread, you've spent x minutes that you'd have to work very hard to get back by saving keystrokes ;)
cut -d\ -f1 ~/.bash_history | sort | uniq -c | sort -rn | head
(Note: There should be two spaces after the -d\ .)
If that doesn't work for you, this might:
history 1 | awk '{print $2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -n | tail | sort -nr
What that doesn't give you is the command tree, for example "git commit" vs "git checkout". It just does "git".
[edit, added gem link] The gem is here https://github.com/paulmars/huffshell
import sys
import collections
tree = lambda: collections.defaultdict(lambda: [0, tree()])
def printtree(node, indent=0):
padding = indent * ' '
for word, (count, child) in node.iteritems():
print "%s%s %d" % (padding, word, count)
printtree(child, indent + 2)
wordtree = tree()
for line in sys.stdin:
node = wordtree
for word in line.split():
node[word][0] += 1
node = node[word][1]
printtree(wordtree)