mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-24 11:37:32 +03:00
Merge remote-tracking branch 'origin/develop' into update-neovim
This commit is contained in:
commit
e7eeaaa975
4
Cartfile
4
Cartfile
@ -4,8 +4,8 @@ github "eonil/FileSystemEvents" == 1.0.0
|
||||
github "sparkle-project/Sparkle" == 1.21.3
|
||||
github "qvacua/CocoaFontAwesome" "master"
|
||||
github "qvacua/CocoaMarkdown" "master"
|
||||
github "qvacua/RxMessagePort" == 0.0.7
|
||||
github "qvacua/RxNeovimApi" == 0.3.4-2
|
||||
github "qvacua/RxMessagePort" == 0.0.9
|
||||
github "qvacua/RxNeovimApi" == 0.3.4-3
|
||||
github "sindresorhus/github-markdown-css" == 3.0.1
|
||||
github "qvacua/swifter" "nonpublic"
|
||||
github "a2/MessagePack.swift" == 3.0.0
|
||||
|
@ -7,9 +7,9 @@ github "elegantchaos/DictionaryCoding" "1.0.6"
|
||||
github "eonil/FileSystemEvents" "1.0.0"
|
||||
github "qvacua/CocoaFontAwesome" "fc2a08babd676525ced68061b19ad8ff3dd1d0b3"
|
||||
github "qvacua/CocoaMarkdown" "c58166490a71ad4d8466f7e7b9faf7cb0917c42f"
|
||||
github "qvacua/RxMessagePort" "v0.0.7"
|
||||
github "qvacua/RxMsgpackRpc" "v0.0.9"
|
||||
github "qvacua/RxNeovimApi" "v0.3.4-2"
|
||||
github "qvacua/RxMessagePort" "v0.0.9"
|
||||
github "qvacua/RxMsgpackRpc" "v0.0.10"
|
||||
github "qvacua/RxNeovimApi" "v0.3.4-3"
|
||||
github "qvacua/ShortcutRecorder" "71baf522a1e57b5f130055e33dcd800687f6ea80"
|
||||
github "qvacua/swifter" "1905655ceedec5b5768f2089ceccf31621f6230a"
|
||||
github "sindresorhus/github-markdown-css" "v3.0.1"
|
||||
|
@ -52,16 +52,6 @@
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
<AdditionalOption
|
||||
key = "MallocStackLogging"
|
||||
value = ""
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
<AdditionalOption
|
||||
key = "PrefersMallocStackLoggingLite"
|
||||
value = ""
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
</AdditionalOptions>
|
||||
<LocationScenarioReference
|
||||
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||
|
@ -352,7 +352,6 @@ public class NvimView: NSView,
|
||||
let ugrid = UGrid()
|
||||
let cellAttributesCollection = CellAttributesCollection()
|
||||
let drawer: AttributesRunDrawer
|
||||
let typesetter = Typesetter()
|
||||
var baselineOffset = 0.cgf
|
||||
|
||||
/// We store the last marked text because Cocoa's text input system does the following:
|
||||
|
@ -6,7 +6,8 @@
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
extension PrimitiveSequence where Element == Never, TraitType == CompletableTrait {
|
||||
extension PrimitiveSequence
|
||||
where Element == Never, TraitType == CompletableTrait {
|
||||
|
||||
func wait(
|
||||
onCompleted: (() -> Void)? = nil,
|
||||
@ -22,15 +23,19 @@ extension PrimitiveSequence where Element == Never, TraitType == CompletableTrai
|
||||
|
||||
let disposable = self.subscribe(onCompleted: {
|
||||
onCompleted?()
|
||||
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
broadcast(condition)
|
||||
condition.broadcast()
|
||||
}, onError: { error in
|
||||
onError?(error)
|
||||
condition.lock()
|
||||
trigger = true
|
||||
err = error
|
||||
broadcast(condition)
|
||||
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
condition.broadcast()
|
||||
})
|
||||
|
||||
while !trigger { condition.wait(until: Date(timeIntervalSinceNow: 5)) }
|
||||
@ -44,8 +49,22 @@ extension PrimitiveSequence where Element == Never, TraitType == CompletableTrai
|
||||
|
||||
extension PrimitiveSequence where TraitType == SingleTrait {
|
||||
|
||||
static func fromSinglesToSingleOfArray(_ singles: [Single<Element>]) -> Single<[Element]> {
|
||||
return Observable.merge(singles.map { $0.asObservable() }).toArray().asSingle()
|
||||
static func fromSinglesToSingleOfArray(
|
||||
_ singles: [Single<Element>]
|
||||
) -> Single<[Element]> {
|
||||
return Observable
|
||||
.merge(singles.map { $0.asObservable() })
|
||||
.toArray()
|
||||
.asSingle()
|
||||
}
|
||||
|
||||
func flatMapCompletable(
|
||||
_ selector: @escaping (Element) throws -> Completable
|
||||
) -> Completable {
|
||||
return self
|
||||
.asObservable()
|
||||
.flatMap { try selector($0).asObservable() }
|
||||
.ignoreElements()
|
||||
}
|
||||
|
||||
func syncValue() -> Element? {
|
||||
@ -59,13 +78,16 @@ extension PrimitiveSequence where TraitType == SingleTrait {
|
||||
|
||||
let disposable = self.subscribe(onSuccess: { result in
|
||||
value = result
|
||||
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
broadcast(condition)
|
||||
condition.broadcast()
|
||||
}, onError: { error in
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
broadcast(condition)
|
||||
condition.broadcast()
|
||||
})
|
||||
|
||||
while !trigger { condition.wait(until: Date(timeIntervalSinceNow: 5)) }
|
||||
@ -74,19 +96,7 @@ extension PrimitiveSequence where TraitType == SingleTrait {
|
||||
return value
|
||||
}
|
||||
|
||||
func flatMapCompletable(_ selector: @escaping (Element) throws -> Completable) -> Completable {
|
||||
return self
|
||||
.asObservable()
|
||||
.flatMap { try selector($0).asObservable() }
|
||||
.ignoreElements()
|
||||
}
|
||||
|
||||
func asCompletable() -> Completable {
|
||||
return self.asObservable().ignoreElements()
|
||||
}
|
||||
}
|
||||
|
||||
private func broadcast(_ condition: NSCondition) {
|
||||
condition.broadcast()
|
||||
condition.unlock()
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
||||
|
||||
source
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onNext: { [unowned self] state in
|
||||
.subscribe(onNext: { state in
|
||||
if state.viewToBeFocused != nil,
|
||||
case .htmlPreview = state.viewToBeFocused! {
|
||||
self.beFirstResponder()
|
||||
|
@ -250,8 +250,9 @@ class MainWindow: NSObject,
|
||||
Observable
|
||||
.of(self.scrollDebouncer.observable, self.cursorDebouncer.observable)
|
||||
.merge()
|
||||
.subscribe(onNext: { [unowned self] action in
|
||||
self.emit(self.uuidAction(for: action))
|
||||
.subscribe(onNext: { [weak self] action in
|
||||
guard let action = self?.uuidAction(for: action) else { return }
|
||||
self?.emit(action)
|
||||
})
|
||||
.disposed(by: self.disposeBag)
|
||||
}
|
||||
@ -259,35 +260,43 @@ class MainWindow: NSObject,
|
||||
private func subscribeToNvimViewEvents() {
|
||||
self.neoVimView.events
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onNext: { [unowned self] event in
|
||||
.subscribe(onNext: { [weak self] event in
|
||||
switch event {
|
||||
|
||||
case .neoVimStopped: self.neoVimStopped()
|
||||
case .setTitle(let title): self.set(title: title)
|
||||
case .setDirtyStatus(let dirty): self.set(dirtyStatus: dirty)
|
||||
case .cwdChanged: self.cwdChanged()
|
||||
case .bufferListChanged: self.bufferListChanged()
|
||||
case .tabChanged: self.tabChanged()
|
||||
case .newCurrentBuffer(let curBuf): self.newCurrentBuffer(curBuf)
|
||||
case .bufferWritten(let buf): self.bufferWritten(buf)
|
||||
case .colorschemeChanged(let theme): self.colorschemeChanged(to: theme)
|
||||
case .neoVimStopped: self?.neoVimStopped()
|
||||
|
||||
case .setTitle(let title): self?.set(title: title)
|
||||
|
||||
case .setDirtyStatus(let dirty): self?.set(dirtyStatus: dirty)
|
||||
|
||||
case .cwdChanged: self?.cwdChanged()
|
||||
|
||||
case .bufferListChanged: self?.bufferListChanged()
|
||||
|
||||
case .tabChanged: self?.tabChanged()
|
||||
|
||||
case .newCurrentBuffer(let curBuf): self?.newCurrentBuffer(curBuf)
|
||||
|
||||
case .bufferWritten(let buf): self?.bufferWritten(buf)
|
||||
|
||||
case .colorschemeChanged(let theme): self?.colorschemeChanged(to: theme)
|
||||
|
||||
|
||||
case .ipcBecameInvalid(let reason):
|
||||
self.ipcBecameInvalid(reason: reason)
|
||||
self?.ipcBecameInvalid(reason: reason)
|
||||
|
||||
case .scroll: self.scroll()
|
||||
case .cursor(let position): self.cursor(to: position)
|
||||
case .initVimError: self.showInitError()
|
||||
case .scroll: self?.scroll()
|
||||
|
||||
case .cursor(let position): self?.cursor(to: position)
|
||||
|
||||
case .initVimError: self?.showInitError()
|
||||
|
||||
case .apiError(let error, let msg):
|
||||
self.log.error("Got api error with msg '\(msg)' and error: \(error)")
|
||||
break
|
||||
self?.log.error("Got api error with msg '\(msg)' and error: \(error)")
|
||||
|
||||
case .rpcEvent(let params):
|
||||
self.rpcEventAction(params: params)
|
||||
case .rpcEvent(let params): self?.rpcEventAction(params: params)
|
||||
|
||||
case .rpcEventSubscribed:
|
||||
break
|
||||
case .rpcEventSubscribed: break
|
||||
|
||||
}
|
||||
}, onError: { error in
|
||||
|
@ -45,7 +45,7 @@ class OpenQuicklyWindow: NSObject,
|
||||
|
||||
source
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onNext: { [unowned self] state in
|
||||
.subscribe(onNext: { state in
|
||||
guard state.openQuickly.open else {
|
||||
self.windowController.close()
|
||||
return
|
||||
@ -68,7 +68,7 @@ class OpenQuicklyWindow: NSObject,
|
||||
)
|
||||
|
||||
self.searchStream
|
||||
.subscribe(onNext: { [unowned self] pattern in
|
||||
.subscribe(onNext: { pattern in
|
||||
self.pattern = pattern
|
||||
self.resetAndAddFilterOperation()
|
||||
})
|
||||
@ -76,7 +76,7 @@ class OpenQuicklyWindow: NSObject,
|
||||
|
||||
self.flatFileItemsSource
|
||||
.subscribeOn(self.scheduler)
|
||||
.do(onNext: { [unowned self] items in
|
||||
.do(onNext: { items in
|
||||
self.scanCondition.lock()
|
||||
while self.pauseScan {
|
||||
self.scanCondition.wait()
|
||||
@ -88,7 +88,7 @@ class OpenQuicklyWindow: NSObject,
|
||||
self.resetAndAddFilterOperation()
|
||||
})
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onNext: { [unowned self] items in
|
||||
.subscribe(onNext: { items in
|
||||
self.count += items.count
|
||||
self.countField.stringValue = "\(self.count) items"
|
||||
})
|
||||
|
@ -93,8 +93,7 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
||||
|
||||
if state.preview.status == .markdown
|
||||
&& state.previewTool.isForwardSearchAutomatically
|
||||
&& state.preview.editorPosition.hasDifferentMark(as: self.editorPosition)
|
||||
{
|
||||
&& state.preview.editorPosition.hasDifferentMark(as: self.editorPosition) {
|
||||
self.forwardSearch(position: state.preview.editorPosition.payload)
|
||||
}
|
||||
|
||||
@ -120,10 +119,13 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
||||
|
||||
self.webviewMessageHandler.source
|
||||
.throttle(0.75, latest: true, scheduler: self.scheduler)
|
||||
.subscribe(onNext: { [unowned self] (position, scrollTop) in
|
||||
self.previewPosition = position
|
||||
self.scrollTop = scrollTop
|
||||
self.emit(UuidAction(uuid: self.uuid, action: .scroll(to: self.previewPosition)))
|
||||
.subscribe(onNext: { [weak self] position, scrollTop in
|
||||
guard let uuid = self?.uuid,
|
||||
let previewPosition = self?.previewPosition else { return }
|
||||
|
||||
self?.previewPosition = position
|
||||
self?.scrollTop = scrollTop
|
||||
self?.emit(UuidAction(uuid: uuid, action: .scroll(to: previewPosition)))
|
||||
})
|
||||
.disposed(by: self.disposeBag)
|
||||
}
|
||||
@ -163,11 +165,11 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
||||
private let webviewMessageHandler = WebviewMessageHandler()
|
||||
|
||||
private let automaticForwardMenuItem = NSMenuItem(title: "Automatic Forward Search",
|
||||
action: nil,
|
||||
keyEquivalent: "")
|
||||
action: nil,
|
||||
keyEquivalent: "")
|
||||
private let automaticReverseMenuItem = NSMenuItem(title: "Automatic Reverse Search",
|
||||
action: nil,
|
||||
keyEquivalent: "")
|
||||
action: nil,
|
||||
keyEquivalent: "")
|
||||
private let refreshOnWriteMenuItem = NSMenuItem(title: "Refresh on Write", action: nil, keyEquivalent: "")
|
||||
|
||||
private let log = OSLog(subsystem: Defs.loggerSubsystem,
|
||||
|
@ -16,14 +16,16 @@ extension ObservableType {
|
||||
}
|
||||
}
|
||||
|
||||
extension PrimitiveSequenceType where TraitType == CompletableTrait, ElementType == Never {
|
||||
extension PrimitiveSequenceType
|
||||
where TraitType == CompletableTrait, ElementType == Never {
|
||||
|
||||
func andThen(using body: () -> Completable) -> Completable {
|
||||
return self.andThen(body())
|
||||
}
|
||||
}
|
||||
|
||||
extension PrimitiveSequence where Element == Never, TraitType == CompletableTrait {
|
||||
extension PrimitiveSequence
|
||||
where Element == Never, TraitType == CompletableTrait {
|
||||
|
||||
func wait() throws {
|
||||
var trigger = false
|
||||
@ -36,13 +38,16 @@ extension PrimitiveSequence where Element == Never, TraitType == CompletableTrai
|
||||
|
||||
let disposable = self.subscribe(onCompleted: {
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
broadcast(condition)
|
||||
condition.broadcast()
|
||||
}, onError: { error in
|
||||
condition.lock()
|
||||
trigger = true
|
||||
err = error
|
||||
broadcast(condition)
|
||||
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
condition.broadcast()
|
||||
})
|
||||
|
||||
while !trigger { condition.wait(until: Date(timeIntervalSinceNow: 5)) }
|
||||
@ -56,11 +61,18 @@ extension PrimitiveSequence where Element == Never, TraitType == CompletableTrai
|
||||
|
||||
extension PrimitiveSequence where TraitType == SingleTrait {
|
||||
|
||||
static func fromSinglesToSingleOfArray(_ singles: [Single<Element>]) -> Single<[Element]> {
|
||||
return Observable.merge(singles.map { $0.asObservable() }).toArray().asSingle()
|
||||
static func fromSinglesToSingleOfArray(
|
||||
_ singles: [Single<Element>]
|
||||
) -> Single<[Element]> {
|
||||
return Observable
|
||||
.merge(singles.map { $0.asObservable() })
|
||||
.toArray()
|
||||
.asSingle()
|
||||
}
|
||||
|
||||
func flatMapCompletable(_ selector: @escaping (Element) throws -> Completable) -> Completable {
|
||||
func flatMapCompletable(
|
||||
_ selector: @escaping (Element) throws -> Completable
|
||||
) -> Completable {
|
||||
return self
|
||||
.asObservable()
|
||||
.flatMap { try selector($0).asObservable() }
|
||||
@ -78,13 +90,16 @@ extension PrimitiveSequence where TraitType == SingleTrait {
|
||||
|
||||
let disposable = self.subscribe(onSuccess: { result in
|
||||
value = result
|
||||
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
broadcast(condition)
|
||||
condition.broadcast()
|
||||
}, onError: { error in
|
||||
condition.lock()
|
||||
defer { condition.unlock() }
|
||||
trigger = true
|
||||
broadcast(condition)
|
||||
condition.broadcast()
|
||||
})
|
||||
|
||||
while !trigger { condition.wait(until: Date(timeIntervalSinceNow: 5)) }
|
||||
@ -93,8 +108,3 @@ extension PrimitiveSequence where TraitType == SingleTrait {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
private func broadcast(_ condition: NSCondition) {
|
||||
defer { condition.unlock() }
|
||||
condition.broadcast()
|
||||
}
|
||||
|
@ -100,7 +100,11 @@ class UiComponentTemplate: UiComponent {
|
||||
case doSth
|
||||
}
|
||||
|
||||
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
|
||||
required init(
|
||||
source: Observable<StateType>,
|
||||
emitter: ActionEmitter,
|
||||
state: StateType
|
||||
) {
|
||||
// set the typed action emit function
|
||||
self.emit = emitter.typedEmit()
|
||||
|
||||
@ -111,7 +115,7 @@ class UiComponentTemplate: UiComponent {
|
||||
source
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(
|
||||
onNext: { [unowned self] state in
|
||||
onNext: { state in
|
||||
Swift.print("Hello, \(self.someField)")
|
||||
}
|
||||
)
|
||||
|
@ -15,18 +15,26 @@ class UiRoot: UiComponent {
|
||||
case quit
|
||||
}
|
||||
|
||||
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
|
||||
required init(
|
||||
source: Observable<StateType>,
|
||||
emitter: ActionEmitter,
|
||||
state: StateType
|
||||
) {
|
||||
self.source = source
|
||||
self.emitter = emitter
|
||||
self.emit = emitter.typedEmit()
|
||||
|
||||
self.fileMonitor = FileMonitor(source: source, emitter: emitter, state: state)
|
||||
self.openQuicklyWindow = OpenQuicklyWindow(source: source, emitter: emitter, state: state)
|
||||
self.fileMonitor = FileMonitor(source: source,
|
||||
emitter: emitter,
|
||||
state: state)
|
||||
self.openQuicklyWindow = OpenQuicklyWindow(source: source,
|
||||
emitter: emitter,
|
||||
state: state)
|
||||
self.prefWindow = PrefWindow(source: source, emitter: emitter, state: state)
|
||||
|
||||
source
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onNext: { [unowned self] state in
|
||||
.subscribe(onNext: { state in
|
||||
let uuidsInState = Set(state.mainWindows.keys)
|
||||
|
||||
uuidsInState
|
||||
@ -39,8 +47,10 @@ class UiRoot: UiComponent {
|
||||
}
|
||||
|
||||
if self.mainWindows.isEmpty {
|
||||
// We exit here if there are no main windows open. Otherwise, when hide/quit after last main window is active,
|
||||
// you have to be really quick to open a new window when re-activating VimR w/o automatic new main window.
|
||||
// We exit here if there are no main windows open.
|
||||
// Otherwise, when hide/quit after last main window is active,
|
||||
// you have to be really quick to open a new window
|
||||
// when re-activating VimR w/o automatic new main window.
|
||||
return
|
||||
}
|
||||
|
||||
@ -48,9 +58,7 @@ class UiRoot: UiComponent {
|
||||
.filter { !uuidsInState.contains($0) }
|
||||
.forEach(self.removeMainWindow)
|
||||
|
||||
guard self.mainWindows.isEmpty else {
|
||||
return
|
||||
}
|
||||
guard self.mainWindows.isEmpty else { return }
|
||||
|
||||
switch state.afterLastWindowAction {
|
||||
|
||||
@ -80,13 +88,19 @@ class UiRoot: UiComponent {
|
||||
private let prefWindow: PrefWindow
|
||||
|
||||
private var mainWindows = [UUID: MainWindow]()
|
||||
private var subjectForMainWindows = [UUID: CompletableSubject<MainWindow.State>]()
|
||||
private var subjectForMainWindows
|
||||
= [UUID: CompletableSubject<MainWindow.State>]()
|
||||
|
||||
private func newMainWindow(with state: MainWindow.State) -> MainWindow {
|
||||
let subject = self.source.compactMap { $0.mainWindows[state.uuid] }.completableSubject()
|
||||
let subject = self
|
||||
.source
|
||||
.compactMap { $0.mainWindows[state.uuid] }
|
||||
.completableSubject()
|
||||
|
||||
self.subjectForMainWindows[state.uuid] = subject
|
||||
return MainWindow(source: subject.asObservable(), emitter: self.emitter, state: state)
|
||||
return MainWindow(source: subject.asObservable(),
|
||||
emitter: self.emitter,
|
||||
state: state)
|
||||
}
|
||||
|
||||
private func removeMainWindow(with uuid: UUID) {
|
||||
|
@ -1,3 +1,7 @@
|
||||
# ???
|
||||
|
||||
* ...
|
||||
|
||||
# 0.26.8-311
|
||||
|
||||
* Bugfix: memory leak
|
||||
|
Loading…
Reference in New Issue
Block a user