Hi,
You may call me a console freak, since I barely exit my terminal, and tend to prefer command line and terminal applications to heavyweight desktop and web-based alternatives.
But I don't go to extremes with that, I'm not obsessed with shell scripting and automation, I don't use mutt, even though I have it configured for my personal Gmail account, and I don't read Slack via IRC, and I don't use text based browsers.
w3m google.com
46l 5j a funny cats q y
ddgr latest ruby version
Today I'd like to share some tricks that help me do repetitive tasks faster, and keep me focused.
I warn you not to repeat my mistake, which is quite common BTW, and don't blindly copy anyone's configuration files. I went through this with zsh, vim, tmux, and ruby related configs. The only way that worked for me is to start from scratch and gradually fill in your tool belt.
Put the things you want to improve to some text file instead, and improve your daily workflow by starting using one helpful thing at a time, only add new things when you develop muscle memory for the previous one.
It's also very good to understand how the things work, so you can fix and tune the way you like it, and not just deal with it and discard a potentially helpful thing when you're completely irritated by its misbehavior.
Also keep in mind that if there's an inconvenience, chances are that someone has fixed this already, you only need to find the fix.
So let's start.
I found myself spending extra seconds opening new browser tab, typing
translate.google.com
, so I've opted in doing translations from the
command line:
trans {fr=} 'bonjour monde'
It translates a given text from Russian to default English. As you may have noticed you get the results are almost instantaneously.
I bet there's no such thing as 'tru' on your system, it's a third-party
utility, coming from a translate-shell
package.
ls -la $(which trans)
But I found the default command syntax hard to remember, so I've created a shell alias for it, so I don't have to remember it every time.
tru 'привет мир'
It's not only less to type, it's much easier to remember, and you don't experience cognitive resistance while using it.
Aliases can save you a couple keystrokes for repetitive commands, but not only that.
git add ...
git commit --amend --no-edit
git push --force-with-lease
bundle exec spring rails console
g a ...
g fixup
g pf
r c
What is even more important, is that you don't need to have feedback, you don't have to read what you type, you just type it and hit Enter, and the computer does what you expect it to do.
Read-evaluate-type loop is poorly implemented in human brain, and the
lag is noticeable. Avoiding it helps you keep focused on the task at
hand instead of reading the text on the screen, jumping your eyes here
and there trying to figure out was that --force-with-lease
or
--lease-with-force
, --skip-edit
or --no-edit
, and how your fancy
command line highlights the errors.
Side note is that I am a bad typist, I mistype very often. And the less I have to type, the less mistakes I make.
I'm going to share what works for me. What makes you more productive might significantly differ, but anyway I hope to deliver the general idea and some things you can derive from.
git
is aliased to g
alias G git
spring rails
is aliased to r
alias G rails
That's mostly all command aliases I need on a daily basis.
You may have noticed some magic in the last commands, specifically the capital G. Bear with me, I'll explain how it works with a pretty self-explaining example:
alias | grep "'|"
can be just:
alias G "'|"
Global aliases can replace any part of the command line, even the argument values:
alias -g junk=node
ls G junk
Disclaimer: I'm aware of the alias -g
to list all the global aliases,
but that wouldn't be a good fit for demonstration purposes.
Again, those aliases are easier to remember and type. You might even end up looking up the documentation that usually is a very time consuming process.
I only use W and G lately, but was the others quite often previously. S is a good alternative to pastebin:
ls /usr/local/lib S
curl --silent <C-V> H 10
I must admit that shell functions are definitely superior to aliases, but harder to read and write unless you're a shell script expert.
You could have written a function that is similar to my trs
alias, but
that wouldn't require adding quotes, e.g.
function trs2 { trans {ru=} "$@" }
trs2 привет мир
Ok, it didn't work as expected, that proves I'm not a shell script expert and explains why I have resorted to using aliases.
I love stretching my brain a little writing obscure commands including shell redirection, pipes, but it's usually a write-once things, it's easier to write then from scratch than to modify:
alias toreman
More on that one later.
Some of the aliases below don't make much sense without some context, which is in my git config.
a for add
c for commit
ca for commit --amend
up for pull (--rebase and --autostash are implied by config)
p for push
s for status (with --short and --branch, but that's just how I like it)
d for diff
ds for diff --staged to see what has been added to the staging area
Some prefer shell aliases to git aliases
alias ga='git add'
ga <Tab>
but it's just a matter of personal preference, autocompletion works equally fine with both.
g a <Tab>
I prefer shell aliases not related to git to reside in separate from git ones, so I prefer to keep them in different files.
To this moment you are probably tired a bit from alias, so let's move to some other topic.
Speaking of the documentation. I hope you don't go to your browser (I'm looking at you, StackOverflow) to find how to use this or that command, and you use proper man pages.
man man
If you find man pages too verbose,
man tar
and often find yourself heading towards the very bottom of the man page, straight to the usage examples, that are often missing, there's tldr (too long don't read) utility for you that gives you some usage examples that in most cases cover your case as well:
? tar
As you may have guessed, question mark stands for tldr, which is hard to type and remember.
There are couple other similar utilities, bropages and cheat that are also good, but to I like tldr better.
Those git aliases support my workflow, as you may guess I use checkpoint commits and then squash them when I feel that a deliverable chunk of work has been done.
fixup to commit --amend --no-edit Adds to the last commit
wip to commit --no-verify --message=wip Commits with a 'wip' comment
Of course, I have to rearrange commits afterward, and I do it with git rebase --interactive:
ri to !BASE_BRANCH=${1:-master} && MERGE_BASE=$(git merge-base origin/$BASE_BRANCH HEAD) && git rebase -i $MERGE_BASE && :. Also hard to grasp, this shows only commits starting from the point where you branched from master. If master or remote master have diverged, that will not affect the results of this command. Trust me, this is essential.
align to !BASE_BRANCH=${1:-master} && git fetch origin $BASE_BRANCH && git rebase origin/$BASE_BRANCH && :
l alias to allow narrowing down the change made in this pull request
$ g l
0a85cb95c9e 2018-03-30 12:08:17 +0300 Filipp Pirozhkov (HEAD -> my-very-important-branch) Change something very important
The definition is very similar to how ri works:
l = !BASE_BRANCH=${1:-master} && MERGE_BASE=$(git merge-base origin/$BASE_BRANCH HEAD) && git log --reverse $MERGE_BASE..HEAD && :
Hard to grasp, but basically it allows you to fetch and rebase on remote master without switching and updating local master.
Don't bother sending pull requests from clunky GitHub UI, use command line and your preferred editor.
hub pull-request -l WIP,needs-review -a pirj
will open your editor with the same template you would see on GitHub. It will automatically add the label and assignee to the pull request.
Trick #1: Remember to use the latest hub, preferably its master branch (e.g. brew install hub --devel), it's required to support pull request templates properly.
Don't be afraid of push-force-with-lease'ing even if work with your colleagues on the same branch and you shuffle/squash/remove commits. Pull, re-arrange, push-force-with-lease.
It's surprising, how many people don't know this trick, but as you can
go to the previous directory with cd -
, you can switch to the
previous branch with git checkout -
.
One useful trick is that you can add the following (last line) to your project's .git/config file:
[remote "origin"]
url = [email protected]:rails/rails.git
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
and that will let you to quickly switch to pull request's branches:
$ g co pr/22396
Branch 'pr/22396' set up to track remote branch 'pr/22396' from 'origin'.
Switched to a new branch 'pr/22396'
$ g l
18d0a5d331f 2018-03-20 19:34:45 +0100 James Bond (HEAD -> pr/22396, origin/pr/22396, origin/steal-microchip) Steal microchip and eliminate all enemy forces
I believe this can also be done with git-pr
command from git-extras
.
An utility called direnv will help you save you some keystrokes.
If your bin
directory has spring
'ified binstubs:
bin/rake
rake
If you use Foreman, and you use pry to set breakpoints, you know how painful it is to actually type something in, because the standard input is shared across processes, and usually the wrong one is getting the inputted text. I have some good news for you (if you use tmux):
toreman
It's a one-line replacement for Foreman, it's parsing the Procfile, and opens split windows for each of the processes. It runs every process in its own tmux pane so you can switch between them, set debug breakpoints and don't have your standard output being shared between them.
You can toggle zoom with C-b z and switch between them with C-b
I, however, use C-e as my tmux prefix, and is not used for any other reason. I find it very hard to put my fingers in a position to press C-a (screen's default one) or tmux's default C-b.
Use it instead of the terminal emulators's tabs, multiple windows and such, it's really powerful, configurable, scriptable, cross-platform, and it also controlled from your keyboard, you won't have to move your mouse to do things.
C-e w - shows sessions
That allows to run rspec in a neigbour window right from the editor.
You may have noticed the --no-verify for the wip alias. This is to skip the overcommit RuboCop checks. However, you should use those checks for regular commits, and run them when doing interactive rebases. You don't want CI to do those checks for you, they run fast locally. This is offered to you by OverCommit for as low as free.
Spring is cool, I've seen last real glitches coming from Spring for months. One known issue is when switching between unrelated branches with diverged schema.db, db:schema:load won't work, spring needs to be stopped before loading the schema.
r db:test:prepare
I don't have an alias for it because if I start typing spring
, the
command is suggested and I accept this even without even looking at the
suggestion.
alias-tips zsh plugin (and zsh-you-should-use), reminds you to use an alias if you happen to type a non-shortened.
You may have noticed the fish shell-like autosuggestions appearing shadowed. I do use double f to accept the suggestion, for me it's even faster than using Tab. I resort to C-r for incremental history search, but I find myself using zsh-autosuggestions significantly more often.
When on command line, I use the same mappings as I use in my editor, that avoids the overhead of mental context switch.
When the command line is large enough that makes it uncomfortable, v
key starts the full-fledged editor that starts in fractions of a second,
allowing to edit text and run the command.
Instead of using new terminal windows, tabs or even tmux panes, it's possible to do several things on the same console.
vim CONTRIBUTING.md
C-z
g s
g a spec
C-z
you're back at your editor! You could run fg, but using the same shortcut is simpler.
You can also go as deep if you want, if you're not afraid to drown.
C-z
vim README.md
C-z
g s
C-z
:q
C-z
It works even if you are typing something, and don't want to lose it, and when copy-paste is an overkill, and when running it and then re-running via history is not an option.
echo Some extremely long line you don't want to lose
C-z
g s
C-z
It's back!
If you touch-type, and look at the command line when you type, not at the fingers or keys. When you start a terminal, the cursor is at the top of it, and after a while it's down below. So each time you switch between different windows, you have to figure out where it is, and that takes some time. I've tuned it to be always at the bottom by printing a number of empty lines.
> show-doc [].map
show-doc is meta, you can find doc by issuing show-doc show-doc
There's a shorthand for show-doc
? 0.odd?
show-source is another helper I use a lot.
show-source Pry::Config
It also has a shorthand, a dollar mark $, which is a bad example of a alias.
In a world of meta-programming, it comes handy to know what was the super definition:
class A
def a
1
end
end
class B < A
def a
super + 3
end
end
b=B.new
show-source b.a
and to find the super definition:
show-source --super b.a
You can go as deep as you want by adding multiple supers:
class C < B
def a
super + 5
end
end
c=C.new
show-source --super --super c.a
and of course there's a shorthand for this syntax:
$ -ss c.a
You are probably familiar with the caller
method that gives you an
idea of the call stack, but with pry it's very noisy, and I use a helper
to filter it out to only include source from the project I'm working on.
caller
trace
However, if you wish to see some code as well,
pry-backtrace
which comes with pry
backtrace
from pry-byebug, and
show-stack
from pry-stack-explorer
Find one that fits your style and needs.
One often overlooked thing is that instead of using continue
to resume
from a breakpoint is to press Ctrl-D.
You should definitely watch the pry presentation that Jonatas referenced on previous productivity sharing session and use
help
command to discover more helpful tools to facilitate debugging.
You may be wondering if it's possible to use pry plugins in a project that doesn't have them in Gemfile. It's possible by using a global RVM gemset and a trick to load it.
irb
You may notice that pry is started on top of irb, and all the installed pry plugins are loaded.
A number of gems are installed automatically when I install a new ruby version, for me it includes:
pry-doc pry-rescue pry-byebug pry-stack_explorer pry-rails guard
guard-shell guard-rubocop terminal-notifier-guard benchmark-ips
rails_best_practices rubycritic
I do track time for myself with timewarrior with:
timew track 1700 - 1745 'Productivity tips' timew summary sod - now # Shows what you did today timew week 2w ago # Shows fancy chart
Use an editor that edits text and mostly only does that. It starts up fast, and I don't miss Eclipse, Intellij IDEA and even TextMate and Sublime that I was using in the past.
Don't even get me started on my editor, and keyboard mapping tricks, ability to do a visual three-way merge from your terminal, history and blame directly from your editor, working with Rails application source files effectively. I'll save this for the next time.
< ~/REFERENCES.md
Also, join #TIL Slack channel if you want to learn and share your tricks.
< RECAP
You'll be able to find references in the slides in the sharing-sessions repo that has an index of the past sessions with all the recordings and slides.
< REFERENCES
Hope you enjoyed the presentation, and found those productivity tips helpful. Please don't hesitate pinging me on Slack with any questions and send me your personal hints and tricks. As always, click like and subscribe.