本文主要讲如何安装第三方开发的Xcode Source Editor Extension。
今天Xcode GM seed版本发布,下载下来后,并没有看到类似插件管理器的东西。目前我获取Xcode Source Editor Extension的方式仅限于在Github上下载源代码,自己编译安装。https://theswiftdev.com/2016/08/17/xcode-8-extensions/中有一些开源插件,有兴趣的同学可以去看一下。我就以其中的ClangFormatter为例,说明一下安装步骤。
首先clone源代码
git clone https://github.com/neonichu/ClangFormatter.git
然后打开ClangFormatter项目,选择ClangFormat进行编译
编译的步骤和注意事项我在Xcode 8 编辑器插件简介 - 1中有详细描述。
编译完后,拷贝Products
下的ClangFormat.appex
到/Applications/Xcode.app/Contents/PlugIns
下
重启Xcode,ClangFormat就在你的Editor下出现了。如果没有出现,可以尝试重启系统,可能Xcode做了某些缓存。
注意
我用的是Xcode GM seed版,在编译ClangFormat时会报错,只要把SourceEditorCommand.swift
做些修改就可以了。修改后代码如下:
//
// SourceEditorCommand.swift
// ClangFormat
//
// Created by Boris Bügling on 21/06/16.
// Copyright © 2016 🚀. All rights reserved.
//
import Foundation
import XcodeKit
class SourceEditorCommand: NSObject, XCSourceEditorCommand {
var commandPath: String {
return Bundle.main.path(forResource: "clang-format", ofType: nil)!
}
func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) {
let errorPipe = Pipe()
let outputPipe = Pipe()
let task = Process()
task.standardError = errorPipe
task.standardOutput = outputPipe
task.launchPath = commandPath
task.arguments = [ "-style=llvm" ]
print("Using clang-format \(task.launchPath)")
let inputPipe = Pipe()
task.standardInput = inputPipe
let stdinHandle = inputPipe.fileHandleForWriting
if let data = invocation.buffer.completeBuffer.data(using: .utf8) {
stdinHandle.write(data)
stdinHandle.closeFile()
}
task.launch()
task.waitUntilExit()
errorPipe.fileHandleForReading.readDataToEndOfFile()
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
if let outputString = String(data: outputData, encoding: .utf8) {
let lines = outputString.characters.split(separator: "\n").map { String($0) }
invocation.buffer.lines.removeAllObjects()
invocation.buffer.lines.addObjects(from: lines)
//invocation.buffer.lines.removeAllObjects()
//invocation.buffer.selections.removeAllObjects()
//invocation.buffer.completeBuffer = outputString
// Crashes Xcode when replacing `completeBuffer`
}
completionHandler(nil)
}
}
主要就是completionHandler: @escaping (Error?) -> Void)
和let task = Process()
有变动,加了@escaping
,把Task()
变成了Process()