I've actually been thinking about how I'd like this for all my typing, but it's difficult to imagine how to do it.
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've certainly found this the case when creating new key bindings for Emacs. Of course, this now means that other people have a little bit of trouble using my Emacs because some of the basic key bindings don't work any more and some of them do something new :).
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.
Yeah, that's the advice I'd give to people starting out in Emacs too. I didn't use it but somehow got the hang of navigating around with the keyboard anyhow. It's probably because I personally did not use the arrow keys before switching to Emacs--I usually used the mouse.
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.
I may misunderstand what you mean, but isn't unmapping standard commands bad for portable scripting? Not everyone will have the same aliases as you; for something like git commit this may not matter, but it seems like a bad habit to me. And again, I may misunderstand what you mean, I don't even know how to make it impossible to type a command.
Aliases typically only apply to interactive usage. From 'man bash':
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).
While I'm not sold on this particular concept, it does highlight a feature of modern Unices which bears pointing out: the command-line environment isn't some dreadful primitive thing that should only be relied on as a last resort.
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.
>But it bears pointing out that this is much like comparing a pogo stick to an F-22 / Boeing 777 / Mercedes E-class.
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).
It's also worth pointing out that many current CLIs are still grossly crippled. The DOS / CMD.exe environment in Windows. Oracle's sql client. Sun/Oracle's default tcsh. Cisco's IOS. All of which lack one or more of readline, tab completion, command history, pipelines, and other, really basic, modern shell features.
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 supported those you mention, and cmd.exe finally has them on by default in recent winders. It is still primitive though in everything else, e.g. scripting. Powershell with its weird syntax is a big improvment, but we split up after XP.
I haven't used Powershell at all. Would've been far better for MSFT to have adopted bash and provided windows-specific utilities where absolutely necessary.
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.
The thing about DOS's globbing is that it wasn't DOS that was doing the globbing, but executables. And they'd do it inconsistently. The executables were also aware if they were passed, say, a '*', and might change their behavior as a consequence (I'm trying to remember whether or not this was actually been the case, can't say, it's been too many years).
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).
True. I remember someone here complaining about that just the other day, said it was a bad idea, but I can't remember why. I prefer the shell doing it.
Hmm. I think my history is a very poor measure of the typing I do. It's the rare command I type that doesn't benefit substantially from tab completion and/or modification of earlier commands.
came here to write this.
For example, if I look at my history, I have a bunch of `git diff` and `bundle exec rake test`, which actually correspond to `<C-r>-d-i` and `<C-r>b`, and a few `heroku ...`which amount to `he<Up>`.
The single command to actually count this occurrences required way more typing.
If you have to do it once, fine. Some work needs to be done.
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!
I fail to see why this is "too much". Pragmatically, for a competent typist, all of these duplicate commands add up to a grand total of what, like 2 minutes a month? You will easily spend a few months of savings performing the analysis and crafting the aliases.
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.
I agree. You need to look at that net time saved, not the gross.
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.
The biggest issue I've had when attempting to customise my shell is the same issue I've had while working with my custom vim setup and that is the issue of a different machine.
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.
Unless of course you only need to write one line. Not every use of git requires complex formatting in commit messages. Almost all of my git repos are used by me alone, and one line is enough. Obviously this isn't the main purpose of git, but I'm guessing I'm not the only developer using it this way.
Additionally, there's significant benefit to lots of tiny commits with a 1 sentence what changed and the squash the commits and write the larger, better formatted one based on your list of one-liners.
I frequently have a commit history that looks something like:
* 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.
I agree with you. It isn't obviously better to write long verbose messages. I commit dozens of times an hour and try and keep each change as small as possible. Ideally, so small a single sentence is a perfect description.
I'll often use Up/^p/^r(i-reverse-search) to find a previous command and edit it's argument, which is where the tree nature of this tool would come in handy. If I 'type' the first n terms of a command enough times, it might be better to alias that part of the command rather than navigate my history and then edit the rest of the command repeatedly.
Better yet, just set your history to 10k-20k+ items and use reverse-search (ie. Ctrl+r in bash) to recall your old commands. Navigation aside, about 80-90% of commands I use regularly are already in the shell history.
On a similar note, I like to periodically clean out my shell history by dropping commands less than a certain Levenshtein edit distance from earlier commands[1]. Looking at the removed lines would probably produce further ideas for optimizing commands; I'll have to try it next time.
[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)
Interesting analysis, once I got it to work. (I have my zsh configured to put history in ~/.zsh_cache/history, not one of the default files. I don't use oh-my-zsh, either.)
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.
For improving your git-command-related efficiency, you could always use the excellent git-sh by Ryan Tomayko (CTO of GitHub): https://github.com/rtomayko/git-sh
Tower is pretty awesome too if you aren't wedded to the command line. I can do things in seconds that would take me awhile to figure out how to do on the command line.
Whenever there is an argument of a CLI being suboptimal you can be sure that the counter is going to be "but it's all in my muscle memory!". CLI itself isn't efficient, it just FEELS efficient. Its real strength is the scriptability, such that repeating tasks can be substituted. If you deny yourself that power, you'd probably be better off with a GUI and good use of hotkeys.
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.
I'd say that administrators who can't set up a system that allows them to have individual setups maybe should pick another job. Even if you're sharing a root account, you could still source your unique shortcuts and aliases. The only thing prevent you from doing that is privileges, of course (although even then there are partial workarounds).
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 ;)
CLI is itself efficient in the sense that you're not lifting your hands from the keyboard to manipulate the mouse. Beyond that - scripting makes it more efficient.
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.