mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-30 16:51:59 +03:00
check versions on starting neovim via the pipe
This commit is contained in:
parent
89e5446b6b
commit
870534c83d
@ -71,7 +71,19 @@ extension NvimView {
|
|||||||
|
|
||||||
self.log.info("NVIM_LISTEN_ADDRESS=\(sockPath)")
|
self.log.info("NVIM_LISTEN_ADDRESS=\(sockPath)")
|
||||||
|
|
||||||
self.bridge.runLocalServerAndNvim(width: size.width, height: size.height)
|
do {
|
||||||
|
try self.bridge.runLocalServerAndNvim(width: size.width, height: size.height)
|
||||||
|
}
|
||||||
|
catch let err as RxNeovimApi.Error {
|
||||||
|
self.eventsSubject.onNext(.ipcBecameInvalid(
|
||||||
|
"Could not launch neovim (\(err))."
|
||||||
|
))
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
self.eventsSubject.onNext(.ipcBecameInvalid(
|
||||||
|
"Could not launch neovim."
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for listen and socket creation to occur
|
// Wait for listen and socket creation to occur
|
||||||
let timeout = Duration.seconds(4)
|
let timeout = Duration.seconds(4)
|
||||||
@ -92,7 +104,12 @@ extension NvimView {
|
|||||||
try?
|
try?
|
||||||
self.api.run(at: sockPath)
|
self.api.run(at: sockPath)
|
||||||
.andThen(
|
.andThen(
|
||||||
self.api.getApiInfo().map {
|
self.api.getApiInfo()
|
||||||
|
.do(onError: { err in
|
||||||
|
throw RxNeovimApi.Error
|
||||||
|
.exception(message: "Could not connect to neovim (\(err)).")
|
||||||
|
})
|
||||||
|
.map {
|
||||||
value in
|
value in
|
||||||
guard let info = value.arrayValue,
|
guard let info = value.arrayValue,
|
||||||
info.count == 2,
|
info.count == 2,
|
||||||
@ -105,13 +122,13 @@ extension NvimView {
|
|||||||
throw RxNeovimApi.Error
|
throw RxNeovimApi.Error
|
||||||
.exception(message: "Could not convert values to api info.")
|
.exception(message: "Could not convert values to api info.")
|
||||||
}
|
}
|
||||||
guard major >= 0 && minor >= 10 || major >= 1
|
guard (major >= kMinAlphaVersion && minor >= kMinMinorVersion) || major >= kMinMajorVersion
|
||||||
else {
|
else {
|
||||||
self.eventsSubject.onNext(.ipcBecameInvalid(
|
self.eventsSubject.onNext(.ipcBecameInvalid(
|
||||||
"Incompatible neovim version \(major).\(minor)"
|
"Incompatible neovim version \(major).\(minor)"
|
||||||
))
|
))
|
||||||
throw RxNeovimApi.Error
|
throw RxNeovimApi.Error
|
||||||
.exception(message: "Could not convert values to api info.")
|
.exception(message: "Incompatible neovim version.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return channel
|
return channel
|
||||||
|
@ -9,6 +9,12 @@ import MessagePack
|
|||||||
import os
|
import os
|
||||||
import RxPack
|
import RxPack
|
||||||
import RxSwift
|
import RxSwift
|
||||||
|
import RxNeovim
|
||||||
|
import RxPack
|
||||||
|
|
||||||
|
let kMinAlphaVersion = 0
|
||||||
|
let kMinMinorVersion = 10
|
||||||
|
let kMinMajorVersion = 1
|
||||||
|
|
||||||
final class UiBridge {
|
final class UiBridge {
|
||||||
init(uuid: UUID, config: NvimView.Config) {
|
init(uuid: UUID, config: NvimView.Config) {
|
||||||
@ -33,11 +39,11 @@ final class UiBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runLocalServerAndNvim(width: Int, height: Int) {
|
func runLocalServerAndNvim(width: Int, height: Int) throws {
|
||||||
self.initialWidth = width
|
self.initialWidth = width
|
||||||
self.initialHeight = height
|
self.initialHeight = height
|
||||||
|
|
||||||
self.launchNvimUsingLoginShellEnv()
|
try self.launchNvimUsingLoginShellEnv()
|
||||||
}
|
}
|
||||||
|
|
||||||
func quit() -> Completable {
|
func quit() -> Completable {
|
||||||
@ -64,7 +70,7 @@ final class UiBridge {
|
|||||||
self.nvimServerProc?.terminate()
|
self.nvimServerProc?.terminate()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func launchNvimUsingLoginShellEnv() {
|
private func launchNvimUsingLoginShellEnv() throws {
|
||||||
var env = self.envDict
|
var env = self.envDict
|
||||||
env["NVIM_LISTEN_ADDRESS"] = self.listenAddress
|
env["NVIM_LISTEN_ADDRESS"] = self.listenAddress
|
||||||
|
|
||||||
@ -103,12 +109,77 @@ final class UiBridge {
|
|||||||
do {
|
do {
|
||||||
try process.run()
|
try process.run()
|
||||||
} catch {
|
} catch {
|
||||||
return
|
throw RxNeovimApi.Error
|
||||||
|
.exception(message: "Could not run neovim process.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try self.doInitialVersionCheck(inPipe: inPipe, outPipe: outPipe)
|
||||||
|
|
||||||
self.nvimServerProc = process
|
self.nvimServerProc = process
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func doInitialVersionCheck(inPipe: Pipe, outPipe: Pipe) throws {
|
||||||
|
|
||||||
|
// Construct Msgpack query for api info
|
||||||
|
let packed = pack(
|
||||||
|
[
|
||||||
|
.uint(RxMsgpackRpc.MessageType.request.rawValue),
|
||||||
|
.uint(UInt64(0)),
|
||||||
|
.string("nvim_get_api_info"),
|
||||||
|
.array([]),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
try inPipe.fileHandleForWriting.write(contentsOf: packed)
|
||||||
|
|
||||||
|
// Read responses from the pipe back
|
||||||
|
var accumulatedData : Data = Data()
|
||||||
|
var values : [MessagePackValue] = []
|
||||||
|
var remainderData: Data? = nil
|
||||||
|
while (true) {
|
||||||
|
let data = outPipe.fileHandleForReading.availableData
|
||||||
|
if data.count == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
accumulatedData.append(data)
|
||||||
|
|
||||||
|
try (values, remainderData) = RxMsgpackRpc.unpackAllWithReminder(accumulatedData)
|
||||||
|
|
||||||
|
if let remainderData { accumulatedData = remainderData }
|
||||||
|
else { accumulatedData.count = 0 }
|
||||||
|
|
||||||
|
if values.count > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate version response
|
||||||
|
guard values.count >= 1,
|
||||||
|
let firstResponse = values[0].arrayValue,
|
||||||
|
firstResponse.count == 4,
|
||||||
|
let rawType = firstResponse[0].uint64Value,
|
||||||
|
let type = RxMsgpackRpc.MessageType(rawValue: rawType),
|
||||||
|
type == RxMsgpackRpc.MessageType.response /* this is a response */,
|
||||||
|
let msgId = firstResponse[1].uint64Value,
|
||||||
|
msgId == 0 /* no confusion on stream */,
|
||||||
|
firstResponse[2] == nil /* no error */,
|
||||||
|
let info = firstResponse[3].arrayValue /* response value */,
|
||||||
|
info.count == 2,
|
||||||
|
let dict = info[1].dictionaryValue,
|
||||||
|
let version = dict["version"]?.dictionaryValue,
|
||||||
|
let major = version["major"]?.intValue,
|
||||||
|
let minor = version["minor"]?.intValue
|
||||||
|
else {
|
||||||
|
throw RxNeovimApi.Error
|
||||||
|
.exception(message: "Could not convert values to api info.")
|
||||||
|
}
|
||||||
|
guard (major >= kMinAlphaVersion && minor >= kMinMinorVersion) || major >= kMinMajorVersion
|
||||||
|
else {
|
||||||
|
throw RxNeovimApi.Error
|
||||||
|
.exception(message: "Incompatible neovim version.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func interactive(for shell: URL) -> Bool {
|
private func interactive(for shell: URL) -> Bool {
|
||||||
if shell.lastPathComponent == "zsh" { return self.usesInteractiveZsh }
|
if shell.lastPathComponent == "zsh" { return self.usesInteractiveZsh }
|
||||||
return true
|
return true
|
||||||
|
@ -202,7 +202,7 @@ public final class RxMsgpackRpc {
|
|||||||
|
|
||||||
if readBytes > 0 {
|
if readBytes > 0 {
|
||||||
dataToUnmarshall.append(readData)
|
dataToUnmarshall.append(readData)
|
||||||
let (values, remainderData) = try self.unpackAllWithReminder(dataToUnmarshall)
|
let (values, remainderData) = try RxMsgpackRpc.unpackAllWithReminder(dataToUnmarshall)
|
||||||
if let remainderData { dataToUnmarshall = remainderData }
|
if let remainderData { dataToUnmarshall = remainderData }
|
||||||
else { dataToUnmarshall.count = 0 }
|
else { dataToUnmarshall.count = 0 }
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ public final class RxMsgpackRpc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func unpackAllWithReminder(_ data: Data) throws -> (values: [Value], remainder: Data?) {
|
public static func unpackAllWithReminder(_ data: Data) throws -> (values: [Value], remainder: Data?) {
|
||||||
var values = [Value]()
|
var values = [Value]()
|
||||||
var remainderData: Data?
|
var remainderData: Data?
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user