-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathshell.html
More file actions
361 lines (254 loc) · 19.5 KB
/
Copy pathshell.html
File metadata and controls
361 lines (254 loc) · 19.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shell Customizations for Python Development — Python 210 6.0 documentation</title>
<script type="text/javascript" src="../../_static/js/modernizr.min.js"></script>
<script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
<script src="../../_static/jquery.js"></script>
<script src="../../_static/underscore.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/javascript" src="../../_static/js/theme.js"></script>
<link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" style="background: #4b2e83" >
<a href="../../index.html">
<img src="../../_static/UWPCE_logo_full.png" class="logo" alt="Logo"/>
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../topics/index.html">Introduction to Python</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../MultipleInheritance.html">15.1.1. Multiple Inheritance</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">Python 210</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content style-external-links">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html">Docs</a> »</li>
<li>Shell Customizations for Python Development</li>
<li class="wy-breadcrumbs-aside">
<a href="../../_sources/modules/dev_environment/shell.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="shell-customizations-for-python-development">
<span id="shell-customization"></span><h1>Shell Customizations for Python Development<a class="headerlink" href="#shell-customizations-for-python-development" title="Permalink to this headline">¶</a></h1>
<p>The command line is your home as a developer. You must be comfortable there.
In order to improve your comfort there are a number of enhancements you can
make to improve your experience, especially with non-standard software like
<code class="docutils literal notranslate"><span class="pre">git</span></code> and <code class="docutils literal notranslate"><span class="pre">virtualenv</span></code></p>
<div class="section" id="what-was-that-name-again">
<h2>What was that name, again?<a class="headerlink" href="#what-was-that-name-again" title="Permalink to this headline">¶</a></h2>
<p>For example, <code class="docutils literal notranslate"><span class="pre">bash</span></code> offers tab completion. But that doesn’t extend to
interactions with <code class="docutils literal notranslate"><span class="pre">git</span></code>. Considering how many branches, tags and remotes you
end up interacting with, and how many long-winded commands there are in
<code class="docutils literal notranslate"><span class="pre">git</span></code>, having a similar autocompletion for them would be very nice.</p>
<p>The folks who create such things have been kind enough to provide a shell
script that sets this up. And it’s not hard to install.</p>
<p><a class="reference external" href="https://github.com/git/git/tree/master/contrib/completion">The script</a> is called <code class="docutils literal notranslate"><span class="pre">git-completion</span></code> and it’s available in <code class="docutils literal notranslate"><span class="pre">bash</span></code>,
<code class="docutils literal notranslate"><span class="pre">tcsh</span></code> and <code class="docutils literal notranslate"><span class="pre">zsh</span></code> flavors.</p>
<p>To use it, download the version of the script that corresponds to your
preferred shell from the tag of the git repo that corresponds to the version of
git you are using. I’ve got git 1.8.4.2 installed on my machine, so
<a class="reference external" href="https://raw.github.com/git/git/v1.8.4.2/contrib/completion/git-completion.bash">this is the version for me</a>. Put it in your home directory:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">cd</span>
$ curl https://raw.github.com/git/git/v1.8.4.2/contrib/completion/git-completion.bash -o .git-completion.bash
</pre></div>
</div>
<p>Then source it from your shell startup file:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">source</span> ~/.git-completion.bash
</pre></div>
</div>
<p>There’s even a nifty gist that <a class="reference external" href="https://gist.github.com/johngibb/972430">does this automatically</a> for OS X.</p>
<p>Once installed, you should be able to visit any repository you have on your
machine and get tab completion of branch names, remotes and all git commands.</p>
</div>
<div class="section" id="where-am-i-what-am-i-doing">
<h2>Where am I, what am I doing?<a class="headerlink" href="#where-am-i-what-am-i-doing" title="Permalink to this headline">¶</a></h2>
<p>As a working developer, you end up with a <em>lot</em> of projects. Even with tab
completion its a chore to remember which branch is checked out, how far ahead
or behind the remote you are, and so on.</p>
<p>Enter <a class="reference external" href="https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh">git-prompt</a>. Again, you place this code in your home directory, and
then source it from your shell startup file:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">source</span> ~/.git-prompt.sh
</pre></div>
</div>
<p>Once you do this you can use the <code class="docutils literal notranslate"><span class="pre">__git_ps1</span></code> shell command and a number of
shell variables to configure <code class="docutils literal notranslate"><span class="pre">PS1</span></code> and change your shell prompt. You can show
the name of the current branch of a repository when you are in one. You can
get information about the status of HEAD, modified files, stashes, untracked
files and more.</p>
<p>There’s two ways to do this. The first is to use <code class="docutils literal notranslate"><span class="pre">__git_ps1</span></code> as a command
directly in a <code class="docutils literal notranslate"><span class="pre">PS1</span></code> expression in your shell startup file:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">export</span> <span class="nv">PS1</span><span class="o">=</span><span class="s1">'[\u@\h \W$(__git_ps1 " (%s)")]\$ '</span>
</pre></div>
</div>
<p>The result looks like this:</p>
<a class="reference internal image-reference" href="../../_images/simple_prompt.png"><img alt="Overriding PS1 provides a customized shell prompt" src="../../_images/simple_prompt.png" style="width: 600px;" /></a>
<p>That’s not bad, but a bit of color would be nice, and perhaps breaking things
onto more than one line so you can parse what you’re seeing more easily would
be helpful.</p>
<p>For that, you’ll need to change strategies. The <code class="docutils literal notranslate"><span class="pre">__git_ps1</span></code> command can be
used as a single element in the expression for <code class="docutils literal notranslate"><span class="pre">PS1</span></code>. But it can also be
used itself as the <code class="docutils literal notranslate"><span class="pre">PROMPT_COMMAND</span></code> env variable (this command is for
<code class="docutils literal notranslate"><span class="pre">bash</span></code>, there’s different one for <code class="docutils literal notranslate"><span class="pre">zsh</span></code>). If defined, this command will be
used to form <code class="docutils literal notranslate"><span class="pre">PS1</span></code> dynamically.</p>
<p>When you use <code class="docutils literal notranslate"><span class="pre">__git_ps1</span></code> in this way, a couple of things happen. First,
instead of taking only one optional argument (a format string), you can provide
two or optionally three arguments:</p>
<ul class="simple">
<li><p>The first will be prepended to the output of the command</p></li>
<li><p>The second will be appended after</p></li>
<li><p>The optional third argumment will be used as a format string for the output
of the command itself. If there is no output, it will not appear at all.</p></li>
</ul>
<p>Combining these three elements can be very expressive. For example, a standard
OS X command prompt can be expressed like so: <code class="docutils literal notranslate"><span class="pre">\h:\W</span> <span class="pre">\u\\\$</span></code>. If you use this
expression as the second argument, leave the first empty and provide a simple format
ending in a newline for the <code class="docutils literal notranslate"><span class="pre">__git_ps1</span></code> output, you get some nice results.</p>
<p>Enter this in your shell startup file:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">PROMPT_COMMAND</span><span class="o">=</span><span class="s1">'__git_ps1 "" "\h:\W \u\\\$ " "[%s]\n"'</span>
</pre></div>
</div>
<p>That produces a nice two-line prompt that appears when you’re in a git repo, and
disappears when you’re not:</p>
<a class="reference internal image-reference" href="../../_images/two_line_prompt.png"><img alt="A two-line prompt showing current git repository" src="../../_images/two_line_prompt.png" style="width: 600px;" /></a>
<p>You can also play with setting a few environment variables in your shell
startup file to expand this further. For example, colorizing the output and
providing information about the state of a repo:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">GIT_PS1_SHOWDIRTYSTATE</span><span class="o">=</span><span class="m">1</span>
<span class="nv">GIT_PS1_SHOWCOLORHINTS</span><span class="o">=</span><span class="m">1</span>
<span class="nv">GIT_PS1_SHOWSTASHSTATE</span><span class="o">=</span><span class="m">1</span>
<span class="nv">GIT_PS1_SHOWUPSTREAM</span><span class="o">=</span><span class="s2">"auto"</span>
<span class="nv">PROMPT_COMMAND</span><span class="o">=</span><span class="s1">'__git_ps1 "" "\h:\W \u\\\$ " "[%s]\n"'</span>
</pre></div>
</div>
<a class="reference internal image-reference" href="../../_images/color_git_prompt.png"><img alt="A colorized git prompt" src="../../_images/color_git_prompt.png" style="width: 600px;" /></a>
<p>Not half bad at all.</p>
</div>
<div class="section" id="but-wait-there-s-more">
<h2>But wait, there’s more.<a class="headerlink" href="#but-wait-there-s-more" title="Permalink to this headline">¶</a></h2>
<p>The problem with this is that it doesn’t play well with another incredibly
useful tool, <a class="reference external" href="http://virtualenv.org">virtualenv</a>. When you activate a virtualenv, it prepends the name
of the environment you are working on to the shell prompt.</p>
<p>But it uses the standard <code class="docutils literal notranslate"><span class="pre">PS1</span></code> shell variable to do this. Since you’ve now
used the <code class="docutils literal notranslate"><span class="pre">PROMPT_COMMAND</span></code> to create your prompt, <code class="docutils literal notranslate"><span class="pre">PS1</span></code> is ignored, and
this nice feature of virtualenv is lost.</p>
<p>Luckily, there is a way out. Bash shell scripting offers <a class="reference external" href="http://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion">parameter expansion</a>
and a trick of that syntax can help. Normally, a shell parameter is
referenced like so:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nv">PARAM</span><span class="o">=</span><span class="s1">'foobar'</span>
$ <span class="nb">echo</span> <span class="nv">$PARAM</span>
foobar
</pre></div>
</div>
<p>In complicated situations, you can wrap the name of the paramter in curly
braces to avoid confusion with following characters:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">echo</span> <span class="si">${</span><span class="nv">PARAM</span><span class="si">}</span>andthennotparam
foobarandthennotparam
</pre></div>
</div>
<p>What is not as well known is that this curly-brace syntax has a lot of
interesting variations. For example, you can use <code class="docutils literal notranslate"><span class="pre">PARAM</span></code> as a test and
actually print something else entirely:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">echo</span> <span class="si">${</span><span class="nv">PARAM</span><span class="p">:+</span><span class="s1">'foo'</span><span class="si">}</span>
foo
$ <span class="nb">echo</span> <span class="si">${</span><span class="nv">PARAM</span><span class="p">:+</span><span class="s1">'bar'</span><span class="si">}</span>
$
</pre></div>
</div>
<p>The key here is the <code class="docutils literal notranslate"><span class="pre">:<char></span></code> bit immediately after <code class="docutils literal notranslate"><span class="pre">PARAM</span></code>. If the <code class="docutils literal notranslate"><span class="pre">+</span></code>
char is present, then if <code class="docutils literal notranslate"><span class="pre">PARAM</span></code> is unset or null, what comes after is not
printed, otherwise it is.</p>
<p>If you look at the script that <a class="reference external" href="https://github.com/pypa/virtualenv/blob/develop/virtualenv_embedded/activate.sh">activates a virtualenv in bash</a> you’ll notice
that it exports <code class="docutils literal notranslate"><span class="pre">VIRTUAL_ENV</span></code>. This means that so long as a virtualenv is
active, this environmental variable will be set. And it will be unset when no
environment is active.</p>
<p>You can use that!</p>
<p>Armed with this knowledge, you can construct a shell expression that will either
print the name of the active virtualenv in square brackets, or print nothing if
no virtualenv was active:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">echo</span> <span class="si">${</span><span class="nv">VIRTUAL_ENV</span><span class="p">:+[</span><span class="sb">`</span>basename <span class="nv">$VIRTUAL_ENV</span><span class="sb">`</span><span class="p">]</span><span class="si">}</span>
$ <span class="nb">source</span> /path/to/someenv/bin/activate
$ <span class="nb">echo</span> <span class="si">${</span><span class="nv">VIRTUAL_ENV</span><span class="p">:+[</span><span class="sb">`</span>basename <span class="nv">$VIRTUAL_ENV</span><span class="sb">`</span><span class="p">]</span><span class="si">}</span>
someenv
</pre></div>
</div>
<p>Roll that into your shell startup file. You’ll have everything you want. You
can even throw in a little more color for good measure:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">source</span> ~/.git-prompt.sh
<span class="c1"># PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '</span>
<span class="nv">GIT_PS1_SHOWDIRTYSTATE</span><span class="o">=</span><span class="m">1</span>
<span class="nv">GIT_PS1_SHOWCOLORHINTS</span><span class="o">=</span><span class="m">1</span>
<span class="nv">GIT_PS1_SHOWSTASHSTATE</span><span class="o">=</span><span class="m">1</span>
<span class="nv">GIT_PS1_SHOWUPSTREAM</span><span class="o">=</span><span class="s2">"auto"</span>
<span class="nv">Color_Off</span><span class="o">=</span><span class="s2">"\[\033[0m\]"</span>
<span class="nv">Yellow</span><span class="o">=</span><span class="s2">"\[\033[0;33m\]"</span>
<span class="nv">PROMPT_COMMAND</span><span class="o">=</span><span class="s1">'__git_ps1 "${VIRTUAL_ENV:+[$Yellow`basename $VIRTUAL_ENV`$Color_Off]\n}" "\h:\W \u\\\$ " "[%s]\n"'</span>
</pre></div>
</div>
<p>And voilà! You’ve got a shell prompt that informs about all the things you’ll
need to know when working on a daily basis:</p>
<a class="reference internal image-reference" href="../../_images/virtualenv_prompt.png"><img alt="A shell session showing the prompt with both virtualenv and git information" src="../../_images/virtualenv_prompt.png" style="width: 600px;" /></a>
</div>
<div class="section" id="wrap-up">
<h2>Wrap-Up<a class="headerlink" href="#wrap-up" title="Permalink to this headline">¶</a></h2>
<p>There is still a great deal more that you could do with your shell, but this
will suffice for now. If you are interested in reading further, there is
<a class="reference external" href="http://www.gnu.org/software/bash/manual/bash.html">a lot to learn</a>.</p>
</div>
</div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>
© Copyright 2020, University of Washington, Natasha Aleksandrova, Christopher Barker, Brian Dorsey, Cris Ewing, Christy Heaton, Jon Jacky, Maria McKinley, Andy Miles, Rick Riehle, Joseph Schilz, Joseph Sheedy, Hosung Song. Creative Commons Attribution-ShareAlike 4.0 license
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>