征服恐惧!用 Vim 写 iOS App

咱们都知道 Vim 和 Emacs 都是文本编辑器中的上古神器,你也许用 ctags,cscopes 配合 Vim 完成过大型 C 或者 C++ 的开发,你也许配合过其余插件,完成过 JavaScript,python 代码的开发,可是不多有人试过 iOS app 的开发吧,毕竟 iOS 的框架包含了不少东西,以及 Objective-C 天生很长的 API 名字,让咱们没办法把此神器用起来,今天我就来给你们讲下我是怎么使用 Vim 开发 iOS App 的,固然 Emacs 也能够php

begin

使用 Vim 开发 iOS App 并非特殊的爱好,而是被 Xcode 8 活生生的逼的,刚开始更新了 Xcode 8 之后,Xcode 8 把第三方插件给屏蔽了,致使没有 XVim 给我用了,没有 XVim 之后,发现异常不顺手,因而尝试用了一段时间的 AppCode,不得不说 AppCode 是一个很是好的 IDE,可是他有个很大的缺点,那就是 Java,JetBrain 家的东西都很不错,惟一缺点就是基于 Java,整个平台都略慢,而后我在不断的 google 过程当中,发现了有人竟不知何谓恐惧,居然使用 Vim 开发 iOS App,最后我也学会了这个新姿式 XDDDDpython

不过目前,只支持 Objective-C 代码的开发,swift 的话,没有解决工程文件自动补全的问题,由于目前你们使用的流行的 swift 自动补全工具 SourceKitten 并无支持 workspace 因此暂时还没用起来git

以及,目前不支持调试,由于发现 Vim 对调试的支持确实好糟糕...github

准备活动

工欲善其事,必先利其器,主角是 Vim 或者 Emacs,少了其余配角和龙套们,也没办法正负恐惧,咱们来看看用到了些什么东西,让咱们的 Vim 成为利器的,这里只是点下他们的名,文章后面会把连接奉上objective-c

  • 首先咱们来看主角队的同窗们,他们是征服恐惧的主力swift

    • macOS,没有神话,开发 iOS 仍是只能在 Mac 上vim

    • 支持 python 的 Vim,能够用 Vim8 或是 neoVim 食用更佳,我就用的 neoVimbash

    • YCMD,其实他是 YouCompleteMe + YouCompelteMeDeamon 的合体,自动补全、定义跳转等功能,就依赖他了app

  • 接下来咱们来看看其余龙套们框架

    • Vbundle,装插件用的,没他,龙套和主角都不用上场了

    • unite + unite-outline + unite-outline-objc,提供了方法导航

    • auto-pairs,自动补全右括号

    • ctrlp,文件搜索跳转

    • Ag,字符串搜索工具

    • syntastic,语法检查工具

    • vim-clang-format,代码格式工具

恩,须要的东西大概就是这些了,Vim 的配置文件,我是基于很久之前 square 开源的 maximum-awesome 的,因此,配合这个食用风味更佳,个人 dot file 也放到了 github 上,欢迎你们 star

进入正题

龙套们,基本均可以经过配置 vbundle 来完成安装,以后只用配置对应的快捷键就行了,这里的正题,要搞定难搞的主 YCMD

难搞的主 YCMD

安装 YCMD

YCMD 的安装很简单,主要是须要必定的配置

首先在 vim 的配置文件中加入下面的内容,更新配置文件并执行 BundleInstall 命令,让 Vbundle 把 YouCompleteMe 插件装上

Plugin 'Valloric/YouCompleteMe'

而后到这个路径 ~/.vim/bundle/YouCompleteMe 这里是 YouCompleteMe 安装的位置,在这里须要编译 YCM,一条命令就能够搞定

./install.py --clang-completer --system-libclang

--clang-completer 告诉脚本咱们须要 clang 的支持,--system-libclang 告诉编译脚本使用系统的 clang,由于以前 clang 升级 4.0 的时候,并无已经编译好的包给我下载,因此这里不用系统 clang 的话,编译脚本会下载一个 clang 3.0,这样就没法支持 iOS 10.0 之后的 sdk 了,由于 iOS 10.0 之后的 sdk 为了支持 swift 引入了一些 clang 3.0 不支持的新语法,因此这里要加上 --system-libclang

而后等他编译完成,这样 YCMD 就配置好了,彷佛这里看并非很难搞,其实难搞的是如何在 iOS 项目中配置好自动提示

为 Xcode 项目配置 YCMD

这里进入到了真正征服恐惧的地方了

YouCompleteMe 的原理

曾经有人说过,编辑器再怎么神器是没办法超过 IDE 的,由于 IDE 是经过编译、解析整个项目的全部文件,来达到语法错误提示,自动补全,定义跳转等高级功能的,而 YCMD 就是来弥补这一个差距的,YCMD 经过传入完整的编译参数,编译须要提示的文件,来实现自动补全,这样没办法超过 IDE 的部分就被抹平了

配置一个项目

这里咱们配置一个复杂的项目来练练手,首先 YCMD 是不可能经过 Xcode 的项目文件或是 workspace 文件获取到编译参数的,因此这一步须要手来,固然,未来能够作成自动的,由于目前手动的作其实很方便,因此如今尚未作成自动的

首先,YCMD 是经过每一个项目路径下的 .ycm_extra_conf.py 脚本文件来获取编译参数的,这个脚本文件中有一个叫作 FlagsForFile 的函数,咱们经过这个函数返回某一个特定文件须要的编译参数,通常状况下大部分文件的编译参数是同样的,咱们来看一个配置的列子

import os
import ycm_core

flags = [
        '-resource-dir',
        '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0',
        '-x objective-c',
        '-arch armv7',
        '-fmessage-length=0',
        # '-fmodules',
        # '-gmodules',
        '-fdiagnostics-show-note-include-stack',
        '-fmacro-backtrace-limit=0',
        '-D__arm__=1',
        '-D__IPHONE_OS_VERSION_MIN_REQUIRED=80000',
        '-std=gnu99',
        '-fobjc-arc',
        '-Wnon-modular-include-in-framework-module',
        '-Werror=non-modular-include-in-framework-module',
        '-Wno-trigraphs',
        '-fpascal-strings',
        '-Os',
        '-fno-common',
        '-Wno-missing-field-initializers',
        '-Wno-missing-prototypes',
        '-Werror=return-type',
        '-Wunreachable-code',
        '-Wno-implicit-atomic-properties',
        '-Werror=deprecated-objc-isa-usage',
        '-Werror=objc-root-class',
        '-Wno-arc-repeated-use-of-weak',
        '-Wduplicate-method-match',
        '-Wno-missing-braces',
        '-Wparentheses',
        '-Wswitch',
        '-Wunused-function',
        '-Wno-unused-label',
        '-Wno-unused-parameter',
        '-Wunused-variable',
        '-Wunused-value',
        '-Wempty-body',
        '-Wconditional-uninitialized',
        '-Wno-unknown-pragmas',
        '-Wno-shadow',
        '-Wno-four-char-constants',
        '-Wno-conversion',
        '-Wconstant-conversion',
        '-Wint-conversion',
        '-Wbool-conversion',
        '-Wenum-conversion',
        '-Wshorten-64-to-32',
        '-Wpointer-sign',
        '-Wno-newline-eof',
        '-Wno-selector',
        '-Wno-strict-selector-match',
        '-Wundeclared-selector',
        '-Wno-deprecated-implementations',
        '-DOBJC_OLD_DISPATCH_PROTOTYPES=0',
        '-isysroot',
        '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',
        '-fstrict-aliasing',
        '-Wprotocol',
        '-Wdeprecated-declarations',
        '-miphoneos-version-min=8.0',
        '-g',
        '-Wno-sign-conversion',
        '-Wno-infinite-recursion',
        '-fembed-bitcode-marker',
        '-I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform',
        '-I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include',
        '-I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks',
        '-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/include',
        '-F/Users/apple/Documents/Developer/CloudLifeWorkspace/iOS/Develop/Project_iOS/project',
        '-MMD',
        '-MT',
        '-MF',
]

SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]

HEADER_EXTENSIONS = [ '.hpp', '.hxx', '.hh', '.h' ]

def FlagsForFile( filename, **kwargs ):
        staticFlags = flags
        return {
                'flags': staticFlags,
                'do_cache': True
        }

这里上面的代码能够看成 .ycmd_extra_conf 文件的一个最小模板,也就是若是咱们的项目里面没有子目录,没有第三方库,那么使用这个已经能够为 iOS 项目提供自动提示了

颤抖吧凡人,如此这般的编译条件,须要你可以把 Xcode 项目配置中的编译参数完彻底全翻译出来才行,可是我也是凡人,因此这个不是我写的,而是有方法生成的,方法以下

把须要增长自动提示的项目用 Xcode 打开,而后编译,而后以下图所示,找到编译信息而后找到项目中的一个文件,注意不要是 Pod 中的文件,最右边,有个三条横线的按钮,点开他,没错,你看到了完整的编译参数,下图中 EXPORT PATH =.... 下面的全部内容就是完整的编译参数

  • Report View

Xcode 中的 Report View

  • 戳这个按钮

Xcode 中的编译信息按钮

  • 咱们要的编译信息

Xcode 中的编译信息

右键,copy,找到你熟悉的记事本,参数都是空格分隔的,因此,这里咱们把它转换成上面代码中的形式,并把不须要的去掉,好比这里我注释了 -fmodules-gmodules 由于这样编译没办法使用 module

把这些加入到配置文件中后,再打开 Vim 你就会发现自动提示变得很是好用了,不过这里还会有一个问题,若是编译的时候,有没法找到 UIKit,这是由于 YCMD 默认引入了 macOS SDK 的路径,致使了编译时 clang 认为咱们编译目标是 macOS,因此以下图须要修改 ~/.vim/bundle/YouCompleteMe/third_party/ycmd/ycmd/completers/cpp/flags.py 文件,去掉默认引入 macOS sdk 的编译参数,这样就行了

须要修改的 YCMD 文件

效果图们

至此,最主要的问题已经被咱们解决了,接下来看下效果如何

  • 首先是自动提示

自动提示

  • 查找文件

文件查找

  • 方法名称大纲

Outline

  • 搜索字符串

搜索字符串

  • 语法检查

语法检查

好处

这么作天然不是为了花样炫技,更多的是为了探索 Vim 的使用,以及更多了解 Xcode 项目

  • 完整的 Vim 环境,写代码不再用碰鼠标了

  • Vim 插件 + 不满的地方本身动手丰衣足食

  • 快速,跟 Vim 比速度,笑话

  • 方便快接的字符串搜索,替换操做

  • 学了点 Python

  • 附赠一个 C/C++ 的开发环境

已知问题

虽然目前已经能够达到写代码的程度了,可是仍是有不少问题,以下:

  • 没办法 debug

  • 不支持 Xcode 中的 group 展现

  • 头文件的提示有问题

  • 不能使用 @import 的导入,会报语法错误

  • xib,storyboard 天然是不行的,个人作法是 Xcode 里面拖 UI + 关联 Outlet + Debug,Vim 中作大量的代码编辑操做

  • [] 方括号的匹配没有 Xcode 那么智能

  • delegate 或是全局的自动提示,须要使用 ctrl + 空格打开,而且有时候会有点慢

  • delegate 的自动提示有时候须要输入前面半部分的方法名才会有,好比上面截图的 tableView,须要先输入 - (void)tableView:(UITableView *)tableView 再使用 ctrl + 空格才会有很是好的自动提示,固然输入前面这部分也会有必定的提示,总体上看能接受

上面的问题都是一直以来我没有解决的问题,你们要是发现有破解的方法,欢迎联系

end

折腾这么多,相信你们已经能够用 Vim 敲 iOS 的代码了,虽然虽然当初开始折腾的时候,踩了不少坑,好比 clang 3 升级 clang 4 后,原来的配置都不能用了,可是收获挺多的也并非这么一篇文章可以说完的,除了 Vim 你们也能够试试 Emacs 下的配置,我用的 Spacemacs,添加了 ycmd 的 layer,配置后也有了相同的效果

也欢迎你们丢砖

参考资料

  • YouCompleteMe: 自动补全插件

  • Vbundle: 插件管理插件

  • Unite: 一个通用的显示插件,能够用来显示各类东西,好比文件列表,buffer 列表,outline

  • Unite-outline: Unite 插件的 outline 插件

  • Unite-outline-objc: Unite-outline 插件的 Objective-C 插件

  • auto-pairs: 自动补全括号的插件

  • ctrlp: 文件查找插件

  • Ag: 字符串查找插件

  • syntastic: 语法检查插件

  • vim-clang-format: clang format 格式化插件

  • VimAwesome: 方便的 Vim 插件导航网站

  • maximum-awesome: 一个比较有名的 Vim 配置,包括了上面的 Vbundle,Ag,ctrlp,syntastic 等插件,以及一些很方便的配置,个人配置文件是基于这个配置的,使用前先安装这个

  • 个人配置文件: 个人配置文件,除了上文写的内容,还加了些 php,python,js 等开发配置,以及一些本身以为用起来方便的配置

相关文章
相关标签/搜索