OC代码规范的spacecommander使用
Posted yohunl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OC代码规范的spacecommander使用相关的知识,希望对你有一定的参考价值。
原文发布在 https://yohunl.com/ocdai-ma-gui-fan-de-spacecommandershi-yong/ ,转载请备注,谢谢
引子
大到每个公司,小到每个人,都有自己的编程习惯,好的编程习惯的保留,得到大家的认同,也就成了规范,目前大体上有几个派系的规范,首当其冲的就是Google的规范.
我们平时在Xcode中的格式规范使用的是苹果的规范Apple’s Guide,不过官方的规范,定义的比较模糊,很多细节方面并没有做出说明,所以很多大公司都在Apple的规范的基础上细化了相关的规范,最典型的当然是Google了.Google的OC规范的说明在Google’s OC Guide,当然了,还有其它一些知名公司也出了自己的规范指导文档,例如Github’s Guide,还有在整个OC业界最知名的培训机构raywenderlich(他们出的ios by tutorials 6,7,8,9,10系列,绝对的经典,是提升之路上必备的经典书籍,没有之一)的规范Raywenderlich’s Guide,当然了,还有markeissler.
以上的几个公司的规范指导,都是非常优秀的,遵循任何一个,对于我们代码的提升都是很有帮助的,但是,这里会有个小小的问题,就是,如果基于自己写代码时候去注意是否符合规范,很容易遗漏,或者是不经意的很多部分就不符合规范了,这时候怎么办?
我们Xcode编译使用的编译器早已经换成开源的LLVM了,LLVM机构给出来一个源码的clang格式工具clang-format,LLVM官方使用的是自己的git服务来存放代码的,有点不方便,有人在github上面建立了其镜像llvm-mirror/clang-tools-extra,如果对此工具感兴趣,可以去读读它的源码.
clang-format是一个命令行的工具,你可以通过源码编译来得到这个工具,也可以用brew来安装(brew install clang-format),安装完了就可以使用了,clang-format的基础用法在ClangFormat基本用法,其内置了四种风格-LLVM, Google, Chromium, Mozilla, WebKit,当然,其也提供了常见的风格配置来支持你的自定义风格(这种自定义风格是有限的,只是在其已有的基础上改变某些配置而已,例如,空格是2个字符还是4个字符等等).
大体上如下这样使用:
// 以Google代码风格格式化NHMineInfo.m,结果输出在终端中
clang-format NHMineInfo.m -style=Google
// 以Google代码风格格式化NHMineInfo.m,结果直接写入文件中
clang-format -i NHMineInfo.m -style=Google
当然了,也可以直接格式化指定的行(-lines)
自定义格式,只需要在工程的目录下提供一个.clang-format文件,在其中指定自定义风格就可以了,这个.clang-format文件的编写,参考官方文档ClangFormat Style Options.
在Xccode8之前,github上有几个包装了clang-format的开源插件,可以用来方便的进行可视化和自动化的代码风格的调整
BBUncrustifyPlugin-Xcode,其代码格式化也是使用的llvm的clang-format(它用到的clang-format是0.39版本)
uncrustify
ClangFormat-Xcode
xcode8以后,已经不支持这种传统方式的插件了,所以需要格式化的话,需要另外的方式.
spacecommander
SpaceCommander为iOS开发团队提供了一个,无需任何手动修改,以统一格式将Object-C代码commit到git仓库的工具。它以git hooks的方式来工作.
何谓git https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks“>Git-Git-Hooks, 其中文版在自定义-Git-Git-钩子,简单来说,git hooks就是Git 能在特定的重要动作发生时触发自定义脚本.理论上,只要我们编写一个git hooks,通过git hooks调用clang-format,那么就可以实现,提交到仓库的所有的代码都是格式化的!
spacecommander的安装
安装很简单,clone spacecommander的代码spacecommander到任意一个目录中.例如,我的电脑上是clone到/Users/yohunl/gitProjects/spacecommander中的.
可以看到,spacecommander是对cang-format的一层包装,让我们使用起来更方便.
为了后期方便使用,我们可以定义环境变量,在 ~/.profile中,添加一行
export SPACECOMMANDER="/Users/yohunl/gitProjects/spacecommander"
那么,以后在命令行中可以直接使用 $SPACECOMMANDER 来代表这个目录.记住这个目录,等下我们需要运行这个目录里的脚本文件.
使用
打开你的某个项目的根目录.例如,示例工程 /Users/yohunl/projects/CustomIOS
$SPACECOMMANDER/setup-repo.sh
备注: 如果你的项目包含了sub module,sub module并不会被添加hooks脚本,如果需要添加,需要进入module,再运行脚本命令
从上面脚本的运行中的回显,可以看到,该命令完成了两件事情
1 添加了隐藏文件 .clang-format文件的替身
2 添加了git hooks ,pre-commit,没有后缀名的那个,凡是带.sample的文件都是示例文件,那是git给你的示例demo,教你写hooks的.
这两个文件是做什么的呢?
我们打开第一个的.clang-format文件,其内容如下:
---
# Custom options in the special build of clang-format (these are not standard options)
IndentNestedBlocks: false
AllowNewlineBeforeBlockParameter: false
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
ConstructorInitializerIndentWidth: 4
SortIncludes: false
AlignAfterOpenBracket: true
AlignEscapedNewlinesLeft: true
AlignOperands: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakTemplateDeclarations: false
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BinPackArguments: true
BinPackParameters: true
ColumnLimit: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 2
KeepEmptyLinesAtTheStartOfBlocks: false
NamespaceIndentation: Inner
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 10000
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
SpacesBeforeTrailingComments: 1
Cpp11BracedListStyle: true
Standard: Auto
IndentWidth: 4
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterCStyleCast: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat: false
...
还记得第一部分,引子中说到的clang-format命令吧,这个文件就是clang-format命令的配置文件,参考官方文档ClangFormat Style Options,大体上就是配置一些代码风格
例如,其中的
IndentWidth: 4
意思是代码的缩进宽度,这里默认的是4个空格,但是由于Google的最新的格式规范中,所有的缩进都是2了,所以我们要根据需要修改这个缩进为2.
第二个文件 pre-commit,是一个git的hooks,其内容如下:
#!/usr/bin/env bash
current_repo_path=$(git rev-parse --show-toplevel)
repo_to_format="/Users/yohunl/projects/CustomIOS"
if [ "$current_repo_path" == "$repo_to_format" ] && [ -e "/Users/yohunl/gitProjects/spacecommander"/format-objc-hook ]; then "/Users/yohunl/gitProjects/spacecommander"/format-objc-hook || exit 1; fi
这个文件,就是在你的工程每次 commit的时候,会预先先执行这里定义的脚本命令!,这段脚本很简单,就是每次commit的时候跑去本地的spacecommander文件夹里运行一个叫做format-objc-hook的文件.
当你commit一段代码的时候,如果代码不符合规范,那么会出提交不了,spacecommander会给出一些提示信息
它会告诉你,这次提交的那个源码中的代码不符合规范,并且指出了格式化的命令.当然了,也可以忽略这次提交的格式化检查(git commit –no-verify,不过我们不建议这么做,因为这样做做,就失去了规范的意义,但是如果你修改第三方的代码,有时候,也是不可避免的,所以忽略还是有存在的意义的).
常用的spacecommander命令
space目录下提供了几个脚本命令
我们最常用的是其中的两个
format-objc-file.sh
这个脚本命令是用来格式化某一个文件的,例如我们要格式化文件 XXX.m,那么可以使用
//注意了,脚本和文件都是需要路径的.否则,默认在本路径下
/Users/yohunl/gitProjects/spacecommander/format-objc-file.sh XXX.m
我们执行这个format-objc-file.sh命令,每次都要输入一大串路径,相对来说比较繁琐,所以我们可以在环境变量中添加一个alias
如果你用的是mac系统的默认终端,那么其环境变量的设置在 ~/.profile文件中,如果你和我一样使用的是zsh,那么就在文件~/.zshrc中添加
alias fmto="$SPACECOMMANDER/format-objc-file.sh"
这样,下次在任何的路径下都可以使用
fmto XXX.m
format-objc-files-in-repo.sh
这个脚本是用来格式化工程中所有的文件的,这个没有参数,直接使用,同理,我们也建立一个alias
alias fmtall="$SPACECOMMANDER/format-objc-files-in-repo.sh"
这个命令,一般都是在初试的时候才使用的,也就是在刚刚建立spacecommander的时候,调用一次,规范化所有的已存在的代码.
这里,你可能会提出一个问题,我们现在工程都大量的使用pods来管理第三方库,那这个命令岂不是将pods中的源码也格式化了?
别担心,spacecommander已经考虑到这个问题了,你可以看spacecommander目录下的/lib/common-lib.sh,看不懂这个脚本没关系,其中有一段代码
其中的
echo "common_sh $files" | grep -v 'Pods/' | grep -v 'Carthage/' >&1
这里就是用正则的方式来过滤掉Pods和Carthaage文件夹的内容的.
另外,你可能还有另一个疑问,那么如果第三方代码,不是通过pods导入的,而是直接添加源码到工程中的(事实上,这个情况很常见),那岂不是又是被格式化了?
还是刚刚那个脚本文件 common-lib.sh
其中也针对这种情况给出了处理的方式
function directories_to_ignore()
if [ -f ".formatting-directory-ignore" ]; then
files=$(echo "$files" | grep -v -f .formatting-directory-ignore)
fi
这段大意是,在.formatting-directory-ignore文件中指定的目录将会被忽略,不会被格式化.那么要处理这种情况就很简单了,在工程下配置一个.formatting-directory-ignore文件,在其中,填写不需要被格式化的文件夹就可以了
这个文件的格式大体上如下所展示:
好了,到此,利用spacecommander来规范化代码,就已经可以了.尽情的享受规范化带来的便利吧.
后记
由于Google的新的规范都是建议缩进是2个空格了(以前都是4个).虽然有了spacecommander这样的规范化的脚本,但是,我们平时桥码代码的时候,编译器还是4个空格的话,就会很不方便,所以还需要调整下Xcode的配置,将其缩进调整为2空格.
参考文档
spacecommander
由spacecommander这个库所想到的自动化管理
spacecommander翻译
shell脚本命令
raywenderlich规范
github规范
google规范
michalrus规范
https://gist.github.com/wangkuiyi/7379a242f0d4089eaa75
https://techblog.badoo.com/blog/2015/09/21/clang-format-as-a-guard-for-objective-c-code-style/
http://www.reviewcode.cn/article.html?reviewId=1
http://www.jianshu.com/p/a6cfe69c5783
插件
https://github.com/benoitsan/BBUncrustifyPlugin-Xcode
https://github.com/Cue/ocstyle
https://github.com/kzaher/RegX
非常完整的包括工程的组织方式建议
swift的代码规范的格式化控件
https://github.com/haaakon/SwiftFormat
https://github.com/Jintin/Swimat 支持xcode8的
https://github.com/qfish/XAlign 代码行对齐的
swift的代码规范
https://github.com/github/swift-style-guide github官方推荐的
https://github.com/raywenderlich/swift-style-guide raywenderlich的推荐规范
oc版本的
https://github.com/raywenderlich/objective-c-style-guide
以上是关于OC代码规范的spacecommander使用的主要内容,如果未能解决你的问题,请参考以下文章