Skip to content

Instantly share code, notes, and snippets.

@pirj
Created August 27, 2018 09:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pirj/6fa22d425d262731a793b200343d0c26 to your computer and use it in GitHub Desktop.
Save pirj/6fa22d425d262731a793b200343d0c26 to your computer and use it in GitHub Desktop.
Productivity tips
RECAP
- don't blindly follow the hints
- figure out what slows you down and takes away your focus
- move forward one confident step at a time
- be confident with the changes you make
- identify the inconveniences that slow you down or distract you, and eliminate them
- rest assured that what slows you down has a solution, you just need to find it

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.

WARM-UP

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

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.

SHELL ALIASES

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.

GLOBAL ALIASES

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

SHELL ALIASES VS SHELL FUNCTIONS

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.

GIT ALIASES

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

SHELL ALIASES VS GIT ALIASES

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.

DOCUMENTATION

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.

MY WEIRD LOCAL GIT WORKFLOW

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.

SENDING PULL-REQUESTS FROM THE COMMAND LINE

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.

GENERAL GIT RECOMMENDATIONS

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.

MORE GIT TIPS

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 = git@github.com: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.

RANDOM TIPS

direnv

An utility called direnv will help you save you some keystrokes. If your bin directory has spring'ified binstubs:

bin/rake
rake

toreman

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.

tmux

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.

RuboCop

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

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

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.

Key mappings in terminal

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.

Ctrl-Z

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!

Cursor in the bottom of the terminal

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.

pry show-doc

> 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?

pry show-source

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

pry show stack

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.

pry in general

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.

pry everywhere

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

Timewarrior

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

General

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.

Outro

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.

REFERENCES
@phil (Filipp Pirozhkov) on Slack
#TIL (Today I Learned) Slack channel
Why command line interfacer matter article:
http://www.cs.pomona.edu/classes/cs181f/supp/cli.html
Shell aliases:
https://github.com/pirj/dotfiles/blob/master/.config/zsh/alias.zsh#L12
Git aliases and config:
https://github.com/pirj/dotfiles/blob/master/.config/git/config#L34
alias-tips for zsh:
https://github.com/djui/alias-tips
Fish-like suggestions, zsh-autosuggestions:
https://github.com/zsh-users/zsh-autosuggestions#zsh-autosuggestions
Trick to use `ff` with zsh-autosuggestions:
https://github.com/pirj/dotfiles/blob/master/.config/zsh/zshrc#L64
Command line interface for GitHub (don't forget to use --devel version):
https://hub.github.com/
Documentation in your Ruby console with pry-doc:
https://github.com/pry/pry-doc#synopsis
Hook to install it:
https://github.com/pirj/dotfiles/blob/master/.gemrc#L9
Automatically install useful gems when new ruby version is installed:
https://github.com/pirj/dotfiles/blob/master/.rvm/hooks/after_install_global
Use pry everywhere and use its plugins:
https://github.com/pirj/dotfiles/blob/master/.irbrc
Fancy C-z trick:
https://github.com/pirj/dotfiles/blob/master/.config/zsh/zshrc#L92
Cursor at the bottom of the screen:
https://github.com/pirj/dotfiles/blob/21a6629e786f41dafa09b56ae34e640326ac4f71/.config/zsh/zshrc#L2
Don't type `bin/` before command
https://direnv.net/
https://github.com/pirj/dotfiles/blob/master/.config/zsh/zshrc#L41
Simplified man pages:
https://github.com/tldr-pages/tldr
https://github.com/chrisallenlane/cheat
http://bropages.org/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment