mirror of
https://github.com/qvacua/vimr.git
synced 2024-12-25 14:52:19 +03:00
GH-264 Monitor and unmonitor urls
This commit is contained in:
parent
74b4740500
commit
c5b5707958
@ -35,6 +35,7 @@ typedef NS_ENUM(NSUInteger, NeoVimServerMsgId) {
|
||||
NeoVimServerMsgIdSetTitle,
|
||||
NeoVimServerMsgIdSetIcon,
|
||||
NeoVimServerMsgIdDirtyStatusChanged,
|
||||
NeoVimServerMsgIdCwdChanged,
|
||||
NeoVimServerMsgIdCommandOutputResult,
|
||||
NeoVimServerMsgIdStop,
|
||||
|
||||
|
@ -602,7 +602,9 @@ void custom_ui_autocmds_groups(
|
||||
return;
|
||||
|
||||
case EVENT_CWDCHANGED:
|
||||
ILOG("cwd changed");
|
||||
[_neovim_server sendMessageWithId:NeoVimServerMsgIdCwdChanged];
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -461,6 +461,10 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
||||
return;
|
||||
}
|
||||
|
||||
case NeoVimServerMsgIdCwdChanged:
|
||||
[_bridge cwdChanged];
|
||||
return;
|
||||
|
||||
case NeoVimServerMsgIdCommandOutputResult: {
|
||||
NSUInteger *values = (NSUInteger *) data.bytes;
|
||||
NSUInteger requestId = values[0];
|
||||
|
@ -113,6 +113,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)setTitle:(NSString *)title;
|
||||
- (void)setIcon:(NSString *)icon;
|
||||
- (void)setDirtyStatus:(bool)dirty;
|
||||
- (void)cwdChanged;
|
||||
|
||||
/**
|
||||
* NeoVim has been stopped.
|
||||
|
@ -1209,6 +1209,12 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
public func cwdChanged() {
|
||||
DispatchUtils.gui {
|
||||
self.delegate?.cwdChanged()
|
||||
}
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
DispatchUtils.gui {
|
||||
self.delegate?.neoVimStopped()
|
||||
|
@ -10,5 +10,6 @@ public protocol NeoVimViewDelegate: class {
|
||||
|
||||
func setTitle(title: String)
|
||||
func setDirtyStatus(dirty: Bool)
|
||||
func cwdChanged()
|
||||
func neoVimStopped()
|
||||
}
|
||||
|
@ -362,6 +362,17 @@
|
||||
path = resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B1AC1AF1D7F395300898F0B /* Open Quickly */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BDF501A1D77596500D8FBC3 /* OpenQuicklyWindowManager.swift */,
|
||||
4BDF50131D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift */,
|
||||
4B22F7F11D7C6B9000929B0E /* ImageAndTextTableCell.swift */,
|
||||
4BAD84E71D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift */,
|
||||
);
|
||||
name = "Open Quickly";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B238BED1D3ED55300CBDD98 /* Preferences */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -483,10 +494,7 @@
|
||||
1929B39DA7AC4A9B62D7CD39 /* Component.swift */,
|
||||
4BD3BF961D32B0DB00082605 /* MainWindowManager.swift */,
|
||||
4BD3BF921D32A95800082605 /* MainWindowComponent.swift */,
|
||||
4BDF501A1D77596500D8FBC3 /* OpenQuicklyWindowManager.swift */,
|
||||
4BDF50131D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift */,
|
||||
4B22F7F11D7C6B9000929B0E /* ImageAndTextTableCell.swift */,
|
||||
4BAD84E71D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift */,
|
||||
4B1AC1AF1D7F395300898F0B /* Open Quickly */,
|
||||
4B238BED1D3ED55300CBDD98 /* Preferences */,
|
||||
);
|
||||
name = UI;
|
||||
|
@ -51,7 +51,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
self.fileItemService.set(ignorePatterns: Set([ "*/.git", "*.o", "*.d", "*.dia" ].map(FileItemIgnorePattern.init)))
|
||||
|
||||
self.prefWindowComponent = PrefWindowComponent(source: self.changeSink, initialData: self.prefStore.data)
|
||||
self.mainWindowManager = MainWindowManager(source: self.changeSink, initialData: self.prefStore.data)
|
||||
self.mainWindowManager = MainWindowManager(source: self.changeSink,
|
||||
fileItemService: self.fileItemService,
|
||||
initialData: self.prefStore.data)
|
||||
self.openQuicklyWindowManager = OpenQuicklyWindowManager(source: self.changeSink,
|
||||
fileItemService: self.fileItemService)
|
||||
|
||||
|
@ -32,4 +32,12 @@ class FileItem : CustomStringConvertible {
|
||||
self.dir = url.dir
|
||||
self.hidden = url.hidden
|
||||
}
|
||||
|
||||
func removeChild(withUrl url: NSURL) {
|
||||
guard let idx = self.children.indexOf({ $0.url == url }) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.children.removeAtIndex(idx)
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ class FileItemService {
|
||||
|
||||
private let fileSystemEventsLatency = Double(2)
|
||||
private var monitors = [NSURL: FileSystemEventMonitor]()
|
||||
private var monitorCounter = [NSURL: Int]()
|
||||
|
||||
private let workspace = NSWorkspace.sharedWorkspace()
|
||||
private let iconsCache = NSCache()
|
||||
@ -78,10 +79,40 @@ class FileItemService {
|
||||
}
|
||||
|
||||
self.monitors[url] = monitor
|
||||
if let counter = self.monitorCounter[url] {
|
||||
self.monitorCounter[url] = counter + 1
|
||||
} else {
|
||||
self.monitorCounter[url] = 1
|
||||
}
|
||||
}
|
||||
|
||||
func unmonitor(url url: NSURL) {
|
||||
guard let counter = self.monitorCounter[url] else {
|
||||
return
|
||||
}
|
||||
|
||||
let newCounter = counter - 1
|
||||
if newCounter > 0 {
|
||||
self.monitorCounter[url] = newCounter
|
||||
} else {
|
||||
self.monitorCounter.removeValueForKey(url)
|
||||
self.monitors.removeValueForKey(url)
|
||||
|
||||
// TODO Remove cached items more aggressively?
|
||||
let hasRelations = self.monitors.keys.reduce(false) { (result, monitoredUrl) in
|
||||
return result ? result : monitoredUrl.parent(ofUrl: url) || url.parent(ofUrl: monitoredUrl)
|
||||
}
|
||||
|
||||
if hasRelations {
|
||||
return
|
||||
}
|
||||
|
||||
self.parentFileItem(ofUrl: url).removeChild(withUrl: url)
|
||||
}
|
||||
}
|
||||
|
||||
private func parentFileItem(ofUrl url: NSURL) -> FileItem {
|
||||
return self.fileItem(forPathComponents: Array(url.pathComponents!.dropLast()))!
|
||||
}
|
||||
|
||||
func flatFileItems(ofUrl url: NSURL) -> Observable<[FileItem]> {
|
||||
|
@ -7,6 +7,21 @@ import Foundation
|
||||
|
||||
extension NSURL {
|
||||
|
||||
func parent(ofUrl url: NSURL) -> Bool {
|
||||
guard self.fileURL && url.fileURL else {
|
||||
return false
|
||||
}
|
||||
|
||||
let myPathComps = self.pathComponents!
|
||||
let targetPathComps = url.pathComponents!
|
||||
|
||||
guard targetPathComps.count > myPathComps.count else {
|
||||
return false
|
||||
}
|
||||
|
||||
return Array(targetPathComps[0..<myPathComps.count]) == myPathComps
|
||||
}
|
||||
|
||||
/// Wrapper function for NSURL.getResourceValue for Bool values.
|
||||
/// Returns also `false` when
|
||||
/// - there is no value for the given `key` or
|
||||
|
@ -13,7 +13,7 @@ enum MainWindowAction {
|
||||
case close(mainWindow: MainWindowComponent)
|
||||
}
|
||||
|
||||
class MainWindowComponent: WindowComponent, NSWindowDelegate, NeoVimViewDelegate {
|
||||
class MainWindowComponent: WindowComponent, NSWindowDelegate {
|
||||
|
||||
private let fontManager = NSFontManager.sharedFontManager()
|
||||
|
||||
@ -24,31 +24,50 @@ class MainWindowComponent: WindowComponent, NSWindowDelegate, NeoVimViewDelegate
|
||||
return self.neoVimView.uuid
|
||||
}
|
||||
|
||||
private var _cwd: NSURL = NSURL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
|
||||
var cwd: NSURL {
|
||||
get {
|
||||
return self.neoVimView.cwd
|
||||
self._cwd = self.neoVimView.cwd
|
||||
return self._cwd
|
||||
}
|
||||
|
||||
set {
|
||||
let oldValue = self._cwd
|
||||
if oldValue == newValue {
|
||||
return
|
||||
}
|
||||
|
||||
self._cwd = newValue
|
||||
self.neoVimView.cwd = newValue
|
||||
self.fileItemService.unmonitor(url: oldValue)
|
||||
self.fileItemService.monitor(url: newValue)
|
||||
}
|
||||
}
|
||||
private let fileItemService: FileItemService
|
||||
|
||||
private let neoVimView = NeoVimView(forAutoLayout: ())
|
||||
|
||||
init(source: Observable<Any>, urls: [NSURL] = [], initialData: PrefData) {
|
||||
init(
|
||||
source: Observable<Any>, fileItemService: FileItemService, cwd: NSURL, urls: [NSURL] = [], initialData: PrefData
|
||||
) {
|
||||
self.defaultEditorFont = initialData.appearance.editorFont
|
||||
self.usesLigatures = initialData.appearance.editorUsesLigatures
|
||||
self.fileItemService = fileItemService
|
||||
self._cwd = cwd
|
||||
|
||||
super.init(source: source, nibName: "MainWindow")
|
||||
|
||||
self.window.delegate = self
|
||||
self.neoVimView.delegate = self
|
||||
|
||||
self.neoVimView.cwd = cwd
|
||||
self.neoVimView.delegate = self
|
||||
self.neoVimView.font = self.defaultEditorFont
|
||||
self.neoVimView.usesLigatures = self.usesLigatures
|
||||
self.neoVimView.open(urls: urls)
|
||||
|
||||
// We don't call self.fileItemService.monitor(url: cwd) here since self.neoVimView.cwd = cwd causes the call
|
||||
// cwdChanged() and in that function we do monitor(...).
|
||||
|
||||
self.window.makeFirstResponder(self.neoVimView)
|
||||
self.show()
|
||||
}
|
||||
@ -109,6 +128,10 @@ extension MainWindowComponent {
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func openQuickly(sender: AnyObject!) {
|
||||
self.publish(event: MainWindowAction.openQuickly(mainWindow: self))
|
||||
}
|
||||
|
||||
@IBAction func saveDocument(sender: AnyObject!) {
|
||||
let curBuf = self.neoVimView.currentBuffer()
|
||||
|
||||
@ -167,10 +190,6 @@ extension MainWindowComponent {
|
||||
// MARK: - Font Menu Items
|
||||
extension MainWindowComponent {
|
||||
|
||||
@IBAction func openQuickly(sender: AnyObject!) {
|
||||
self.publish(event: MainWindowAction.openQuickly(mainWindow: self))
|
||||
}
|
||||
|
||||
@IBAction func resetFontSize(sender: AnyObject!) {
|
||||
self.neoVimView.font = self.defaultEditorFont
|
||||
}
|
||||
@ -191,7 +210,7 @@ extension MainWindowComponent {
|
||||
}
|
||||
|
||||
// MARK: - NeoVimViewDelegate
|
||||
extension MainWindowComponent {
|
||||
extension MainWindowComponent: NeoVimViewDelegate {
|
||||
|
||||
func setTitle(title: String) {
|
||||
self.window.title = title
|
||||
@ -201,6 +220,13 @@ extension MainWindowComponent {
|
||||
self.windowController.setDocumentEdited(dirty)
|
||||
}
|
||||
|
||||
func cwdChanged() {
|
||||
let old = self._cwd
|
||||
self._cwd = self.neoVimView.cwd
|
||||
self.fileItemService.unmonitor(url: old)
|
||||
self.fileItemService.monitor(url: self._cwd)
|
||||
}
|
||||
|
||||
func neoVimStopped() {
|
||||
self.windowController.close()
|
||||
}
|
||||
@ -214,6 +240,7 @@ extension MainWindowComponent {
|
||||
}
|
||||
|
||||
func windowWillClose(notification: NSNotification) {
|
||||
self.fileItemService.unmonitor(url: self._cwd)
|
||||
self.publish(event: MainWindowAction.close(mainWindow: self))
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,11 @@ class MainWindowManager: StandardFlow {
|
||||
private var mainWindowComponents = [String:MainWindowComponent]()
|
||||
private weak var keyMainWindow: MainWindowComponent?
|
||||
|
||||
private let fileItemService: FileItemService
|
||||
private var data: PrefData
|
||||
|
||||
init(source: Observable<Any>, initialData: PrefData) {
|
||||
init(source: Observable<Any>, fileItemService: FileItemService, initialData: PrefData) {
|
||||
self.fileItemService = fileItemService
|
||||
self.data = initialData
|
||||
|
||||
super.init(source: source)
|
||||
@ -27,9 +29,8 @@ class MainWindowManager: StandardFlow {
|
||||
|
||||
func newMainWindow(urls urls: [NSURL] = [], cwd: NSURL = MainWindowManager.userHomeUrl) -> MainWindowComponent {
|
||||
let mainWindowComponent = MainWindowComponent(
|
||||
source: self.source, urls: urls, initialData: self.data
|
||||
source: self.source, fileItemService: self.fileItemService, cwd: cwd, urls: urls, initialData: self.data
|
||||
)
|
||||
mainWindowComponent.cwd = cwd
|
||||
self.mainWindowComponents[mainWindowComponent.uuid] = mainWindowComponent
|
||||
|
||||
mainWindowComponent.sink
|
||||
@ -38,9 +39,12 @@ class MainWindowManager: StandardFlow {
|
||||
.subscribeNext { [unowned self] action in
|
||||
switch action {
|
||||
case let .becomeKey(mainWindow):
|
||||
self.setKeyWindow(mainWindow)
|
||||
self.set(keyMainWindow: mainWindow)
|
||||
|
||||
case .openQuickly:
|
||||
Swift.print(action)
|
||||
self.publish(event: action)
|
||||
|
||||
case let .close(mainWindow):
|
||||
self.closeMainWindow(mainWindow)
|
||||
}
|
||||
@ -81,7 +85,7 @@ class MainWindowManager: StandardFlow {
|
||||
keyMainWindow.open(urls: urls)
|
||||
}
|
||||
|
||||
func setKeyWindow(mainWindow: MainWindowComponent?) {
|
||||
private func set(keyMainWindow mainWindow: MainWindowComponent?) {
|
||||
self.keyMainWindow = mainWindow
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user