# 写给 Pythoner 的 Spacemacs 入门指北

最开始,使用 Sublime Text 编码,后来用 Vim 混合 PyCharm 写 Python。

前几天,Github 上的 Spacemacs 已经成功的突破一万 Star, 听说几个我非常佩服的 Pythoner(比如『Python Web 开发实战』的作者董伟明) 也是非常喜欢 Spacemacs, 我就萌生了从 Vim 切换到 Spacemacs 的想法,说做就做。

注:本文所有内容基于 macOS 10.11, 软件环境为 zsh , pyenv , python3.5.2 , node5.12.0. 其他类 Unix 平台略作修改即可使用。至于 Windows 平台,建议安装 Ubuntu 虚拟机。本文也需要读者具备基本的 VIM 基本常识和 Python 常识。

本文只负责把读者带入 Spacemacs 的世界中,而不是涉及到 Spacemacs 的方方面面,所以此文为指北。而非详细的指南 (Guide).

# 0x00 基本软件环境安装

# zsh 与 ohmyzsh

brew install zsh
chsh -s /bin/zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

# pyenv 与 pyenv virtualenv

git clone https://github.com/yyuu/pyenv.git ~/.pyenv
git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zshrc

# 不喜写兼容代码,所有代码均向 3.5+ 靠拢
v=3.5.2|wget http://mirrors.sohu.com/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/;pyenv install $v
v=3.6.0|wget http://mirrors.sohu.com/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/;pyenv install $v
v=2.7.11|wget http://mirrors.sohu.com/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/;pyenv install $v

# 设置 Global Python 为 2.7.11, 备注:尽量不要把 Py3 设置为全局,否则由于 Homebrew 本身有一些依赖是依赖于 Py2 的,这样容易出现一些奇怪的问题。
pyenv global 2.7.11
pip install -i https://pypi.doubanio.com/simple requests
# 下面这个是用于安装基本的代码补全功能
pip install -i https://pypi.doubanio.com/simple --upgrade "jedi>=0.9.0" "json-rpc>=1.8.1" "service_factory>=0.1.5" flake8 pytest autoflake hy

pyenv virtualenv 3.5.2 py3-daily
pyenv activate py3-daily
pip install -i https://pypi.doubanio.com/simple requests
pip install -i https://pypi.doubanio.com/simple beatutifulsoup4
pip install -i https://pypi.doubanio.com/simple ipython[notebook]
pip install -i https://pypi.doubanio.com/simple jupyter
# 下面这个是用于安装基本的代码补全功能
pip install -i https://pypi.doubanio.com/simple --upgrade "jedi>=0.9.0" "json-rpc>=1.8.1" "service_factory>=0.1.5" flake8 pytest autoflake hy
pyenv deactivate
# pyenv uninstall py3-daily

# nvm 以及常用 npm 包

# 安装 nvm
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash
nvm install 5.12.0
echo '\n#alias for cnpm\nalias cnpm="npm --registry=https://registry.npm.taobao.org \
  --cache=$HOME/.npm/.cache/cnpm \
  --disturl=https://npm.taobao.org/dist \
  --userconfig=$HOME/.cnpmrc"' >> ~/.zshrc && source ~/.zshrc
npm install -g vmd
npm install -g gitbook-cli
npm install -g hexo-cli
npm install -g tern
npm install -g js-beautify
npm install -g js-hint

# Spacemacs 安装以及基本配置

brew install ag
brew install grep
brew tap d12frosted/emacs-plus
brew install emacs-plus
# 安装完毕之后,克隆我的配置 repo, 有一些基本的配置用于解决墙的问题。解决方案来自于子龙山人
git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d
mv ~/.spacemacs .spacemacs.bak
git clone https://github.com/twocucao/spacemacs.d.git ~/.spacemacs.d
# 输入 emacs 进行初始化,如果你可以正常访问 Github 的话时间在半小时之内。
emacs

安装 Spacemacs 过程中画面如下:

安装 Spacemacs 过程中画面

安装前,Emacs 长这个样子:

安装前

安装后,Emacs 长这个样子:

安装后.png

在正式进入,请牢牢记住下面几个按键已经功能,以备不时之需

  • spc : 跳出命令面板
  • spc-spc : 跳出命令列表,可运行命令,也可以查找快捷键
  • spc-h-spc : 查找包的用途与定义

嗯,可以谈下一话题了!

# 0x01 日常的编辑

# 1.1 文件导航

  • (VIM 流)hjkloOaA zz
  • (VIM 流)查找 * /words
  • spc-f-j 开发 neotree
  • spc-tab 切换到上一个 buffer
  • spc-f-f 打开文件 spc-p-f fuzzfind 类似于 ctrlp spc-s-g-p grep 搜索项目 spc-s-a-p ag 搜索项目

搜索项目如图 (spc-s-a-p ag 搜索项目):

按照关键字搜索项目

实在是方便至极

# 1.2 文件编辑

文件内容编辑

  • (VIM 流)u 与 c-r d c 等
  • 有趣的是查找替换功能也是自带预览的。比如 :%s/foo/bar/g

查找替换预览

文件本身编辑

  • 在 dired mode 下:copy - C , delete - D, new folder - +
  • 也可以 spc-f-t 在 neotree 下进行编辑

除去这些和 Vim 相似的文件编辑功能之外,甚至窗口管理都和 Vim 一致了,使用 c-w+hjkl 直接跳转。
强烈建议在读者抽空过一遍基本的 Vimtutor

# 1.3 Markdown Writing

  • spc-spc-markdown-generate-to 回车即可生成本文的 Toc(Table Of Content)
  • spc-b-i 打开 buffer 的 imenu(类似于 Vim 的 Tagbar 插件),enter 跳转

搜索项目如图 (spc-b-i 开启 buffer imenu ,enter 跳转):

IMenu

# 0x02. Python 编程

# 2.1 代码补全

当你按照前面的所有配置走一圈下来,基本上就已经可以完美的进行补全了。
比如,当我编辑一个 py 文件的时候,

# 先激活虚拟环境
pyenv activate 3.5.2/envs/py3-daily
emacs py.py

如图所示,因为 requests,numpy 这种第三方库都可以完美补全,其他自然不在话下。

代码补全

代码补全还有另一个神器,就是可以内嵌 lisp 的 Snippet 模板 – yasnippet, 由于模板功能基本上和其他编辑器相同,而使用 elisp 语言进行编写动态 Snippet 模板则需要会 elisp, 这以后有机会再学学。

# 2.2 代码跳转

  • 文件代码跳转 spc-spc-helm-imenu 查看文件结构
  • 文件跳转 在 normal-mode 下,gd 即可跳转到函数定义上,但是不能跨文件跳转。

单文件使用 helm_imenu 进行浏览

使用 ag 进行代码搜索

# 2.3 pytest 测试

  • spc-m-s-py3-daily enter 选择 py3-daily 虚拟环境
  • spc-spc-pytest-all enter 即可运行所有 pytest 测试。

测试过程:

运行测试失败,运行测试失败,使用 c-w-j 跳转到下面窗口,对红色标记处 enter, 即可跳转到出错文件行。

pytest 运行测试失败

修正运行测试成功,如图:

pytest 运行测试成功

# 0x03. IPython Notebook

通常情况下我使用 IPython Notebook 都是在 Web 端,因为是 Web 端,实际上大量的 Dom 渲染对浏览器的渲染速度还是有一定的影响的,我还是比较喜欢客户端,因为客户端的快捷键可以定制,而 Web 端的快捷键实在是相当的不方便。

是不是 IPython Notebook 的 web 端没有好处呢?有的,比如我可以借用外部的 JS 可视化图表对 js 进行可视化呀。

比如我发在简书上的这篇技术文 IPython Notebook 引入 ECharts 做可视化

但,如果不需要 js 功能的话,还是用客户端舒服一些。

# 3.1 IPython Notebook 基本配置

spacemacs 貌似只支持密码访问 IPython Notebook, 那么我们就生成密码。

# 首先激活 py3-daily 环境
python -c "from notebook.auth import passwd;print(passwd())" | pbcopy
# 恩,于是剪切板上就有如下的字符串
sha1:9bf4c48a6b83:26bc24a78a1e4aea7baa36874f5e86bafac0dbb9
# 打开 config 文件取消注释并修改 c.NotebookApp.password
vim ~/.jupyter/jupyter_notebook_config.py
c.NotebookApp.password = 'sha1:35543659622f:f9a78f0b20132f3e04aa1d4ed4060f9fd9eb7663'

# 3.2 Emacs IPython Notebook

# 首先在终端打开 IPython Notebook
ipython notebook

接着打开 emacs, 输入 spc-a-i-n, 默认端口,然后输入密码即可。首次登陆后还需要在输入一次 spc-a-i-n 即可看到 IPython Notebook 的主界面。

IPYNB 的主界面

光标移到 [New Notebook] 键击 enter 新建 IPython Notebook.

输入如下代码:

# The %... is an iPython thing, and is not part of the Python language.
# In this case we're just telling the plotting library to draw things on
# the notebook, instead of on a separate window.
%matplotlib inline
# See all the "as ..." contructs? They're just aliasing the package names.
# That way we can call methods like plt.plot() instead of matplotlib.pyplot.plot().
import numpy as np
import scipy as sp
import matplotlib as mpl
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import pandas as pd
import time
pd.set_option('display.width', 1000)
pd.set_option('display.max_columns', 100)
pd.set_option('display.notebook_repr_html', True)
import seaborn as sns
sns.set_style("darkgrid")
sns.set_context("poster")
sns.set()

# Load the example flights dataset and conver to long-form
flights_long = sns.load_dataset("flights")
flights = flights_long.pivot("month", "year", "passengers")

# Draw a heatmap with the numeric values in each cell
sns.heatmap(flights, annot=True, fmt="d", linewidths=.5)

shift+enter , 咣

热力图就出来了

热力图

# 0x04. 扩展

看完上文,就可以深入文档进行探索了。

ChangeLog:

  • 2017-01-15 18:53:45 重修文字
  • 2017-01-16 12:49:19 润饰文字,增加可读性,首发简书。
  • 2018-01-01 12:49:19 最后弃坑并回归 Vim 与 IDE