From 28e092ab40729551af05a5de7d94aabcbf66ece0 Mon Sep 17 00:00:00 2001 From: Tae Won Ha Date: Fri, 1 Dec 2017 13:46:34 +0100 Subject: [PATCH] Use API to get tabs --- NeoVimServer/NeoVimMsgIds.h | 1 - NeoVimServer/NeoVimServer.m | 2 - NeoVimServer/server_globals.h | 1 - NeoVimServer/server_ui.m | 61 ----------------------- NvimMsgPack/NvimMsgPack/Nvim.swift | 13 ++++- NvimMsgPack/NvimMsgPack/NvimMethods.swift | 34 +++++++++++++ SwiftNeoVim/NeoVimAgent.h | 2 - SwiftNeoVim/NeoVimAgent.m | 20 -------- SwiftNeoVim/NeoVimView+Api.swift | 45 +++++++++++++++-- SwiftNeoVim/NeoVimView+TouchBar.swift | 4 +- bin/generate_api_methods.py | 1 + 11 files changed, 90 insertions(+), 94 deletions(-) diff --git a/NeoVimServer/NeoVimMsgIds.h b/NeoVimServer/NeoVimMsgIds.h index 53af4c05..fd091ccd 100644 --- a/NeoVimServer/NeoVimMsgIds.h +++ b/NeoVimServer/NeoVimMsgIds.h @@ -59,7 +59,6 @@ typedef NS_ENUM(NSInteger, NeoVimAgentMsgId) { NeoVimAgentMsgIdGetPwd, NeoVimAgentMsgIdGetEscapeFileNames, - NeoVimAgentMsgIdGetTabs, NeoVimAgentMsgIdGetBoolOption, NeoVimAgentMsgIdSetBoolOption, diff --git a/NeoVimServer/NeoVimServer.m b/NeoVimServer/NeoVimServer.m index 7a0580ca..8419d606 100644 --- a/NeoVimServer/NeoVimServer.m +++ b/NeoVimServer/NeoVimServer.m @@ -72,8 +72,6 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD case NeoVimAgentMsgIdScroll: return data_sync(data, outputCondition, neovim_scroll); - case NeoVimAgentMsgIdGetTabs: return data_sync(data, outputCondition, neovim_tabs); - case NeoVimAgentMsgIdGetBoolOption: return data_sync(data, outputCondition, neovim_get_bool_option); case NeoVimAgentMsgIdSetBoolOption: return data_sync(data, outputCondition, neovim_set_bool_option); diff --git a/NeoVimServer/server_globals.h b/NeoVimServer/server_globals.h index 852cddf2..968ea8be 100644 --- a/NeoVimServer/server_globals.h +++ b/NeoVimServer/server_globals.h @@ -15,7 +15,6 @@ extern void start_neovim(NSInteger width, NSInteger height, NSArray extern void neovim_select_window(void **argv); extern void neovim_scroll(void **argv); -extern void neovim_tabs(void **argv); extern void neovim_vim_command_output(void **argv); extern void neovim_set_bool_option(void **argv); extern void neovim_get_bool_option(void **argv); diff --git a/NeoVimServer/server_ui.m b/NeoVimServer/server_ui.m index 4ded2d8d..2d23ca7c 100644 --- a/NeoVimServer/server_ui.m +++ b/NeoVimServer/server_ui.m @@ -684,32 +684,6 @@ static NSString *escaped_filename(NSString *filename) { return result; } -static NeoVimBuffer *buffer_for(buf_T *buf) { - // To be sure... - if (buf == NULL) { - return nil; - } - - bool readonly = (bool) bt_nofile(buf); - - NSString *fileName = nil; - if (buf->b_ffname != NULL) { - fileName = [NSString stringWithCString:(const char *) buf->b_ffname - encoding:NSUTF8StringEncoding]; - } - - bool current = curbuf == buf; - bool dirty = readonly ? false : (bool) buf->b_changed; - - NeoVimBuffer *buffer = [[NeoVimBuffer alloc] initWithHandle:buf->handle - unescapedPath:fileName - dirty:dirty - readOnly:readonly - current:current]; - - return [buffer autorelease]; -} - void neovim_scroll(void **argv) { work_and_write_data_sync(argv, ^NSData *(NSData *data) { NSInteger *values = (NSInteger *) data.bytes; @@ -770,41 +744,6 @@ void neovim_select_window(void **argv) { }); } -void neovim_tabs(void **argv) { - work_and_write_data_sync(argv, ^NSData *(NSData *data) { - NSMutableArray *tabs = [[NSMutableArray new] autorelease]; - FOR_ALL_TABS(t) { - NSMutableArray *windows = [NSMutableArray new]; - - bool currentTab = curtab ? t->handle == curtab->handle : false; - - FOR_ALL_WINDOWS_IN_TAB(win, t) { - NeoVimBuffer *buffer = buffer_for(win->w_buffer); - if (buffer == nil) { - continue; - } - - bool current = false; - // tp_curwin is only valid for tabs that aren't the current one - if (currentTab) current = curwin ? win->handle == curwin->handle : false; - else if (t->tp_curwin) current = win->handle == t->tp_curwin->handle; - NeoVimWindow *window = [[NeoVimWindow alloc] initWithHandle:win->handle buffer:buffer currentInTab:current]; - [windows addObject:window]; - [window release]; - } - - NeoVimTab *tab = [[NeoVimTab alloc] initWithHandle:t->handle windows:windows current:currentTab]; - [windows release]; - - [tabs addObject:tab]; - [tab release]; - } - - DLOG("tabs: %s", tabs.description.cstr); - return [NSKeyedArchiver archivedDataWithRootObject:tabs]; - }); -} - void neovim_vim_command_output(void **argv) { work_and_write_data_sync(argv, ^NSData *(NSData *data) { NSString *input = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; diff --git a/NvimMsgPack/NvimMsgPack/Nvim.swift b/NvimMsgPack/NvimMsgPack/Nvim.swift index 467f4828..00f54974 100644 --- a/NvimMsgPack/NvimMsgPack/Nvim.swift +++ b/NvimMsgPack/NvimMsgPack/Nvim.swift @@ -21,7 +21,11 @@ public class Nvim { } } - public struct Window { + public struct Window: Equatable { + + public static func ==(lhs: Window, rhs: Window) -> Bool { + return lhs.handle == rhs.handle + } public let handle: Int @@ -30,7 +34,11 @@ public class Nvim { } } - public struct Tabpage { + public struct Tabpage: Equatable { + + public static func ==(lhs: Tabpage, rhs: Tabpage) -> Bool { + return lhs.handle == rhs.handle + } public let handle: Int @@ -206,6 +214,7 @@ public class Nvim { self.session.stop() } + @discardableResult public func checkBlocked(_ fn: () -> Nvim.Response) -> Nvim.Response { if self.getMode().value?.dictionaryValue?[.string("blocked")] == .bool(true) { return Nvim.Response.failure(Nvim.Error(type: .blocked, message: "Nvim is currently blocked.")) diff --git a/NvimMsgPack/NvimMsgPack/NvimMethods.swift b/NvimMsgPack/NvimMsgPack/NvimMethods.swift index c6899d0e..72204481 100644 --- a/NvimMsgPack/NvimMsgPack/NvimMethods.swift +++ b/NvimMsgPack/NvimMsgPack/NvimMethods.swift @@ -64,6 +64,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func bufSetLines( buffer: Nvim.Buffer, start: Int, @@ -156,6 +157,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func bufSetVar( buffer: Nvim.Buffer, name: String, @@ -177,6 +179,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func bufDelVar( buffer: Nvim.Buffer, name: String, @@ -219,6 +222,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func bufSetOption( buffer: Nvim.Buffer, name: String, @@ -261,6 +265,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func bufSetName( buffer: Nvim.Buffer, name: String, @@ -355,6 +360,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func bufClearHighlight( buffer: Nvim.Buffer, src_id: Int, @@ -422,6 +428,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func tabpageSetVar( tabpage: Nvim.Tabpage, name: String, @@ -443,6 +450,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func tabpageDelVar( tabpage: Nvim.Tabpage, name: String, @@ -525,6 +533,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func uiAttach( width: Int, height: Int, @@ -546,6 +555,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func uiDetach( expectsReturnValue: Bool = true ) -> Nvim.Response { @@ -562,6 +572,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func uiTryResize( width: Int, height: Int, @@ -581,6 +592,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func uiSetOption( name: String, value: Nvim.Value, @@ -600,6 +612,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func command( command: String, expectsReturnValue: Bool = true @@ -663,6 +676,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func feedkeys( keys: String, mode: String, @@ -861,6 +875,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func setCurrentDir( dir: String, expectsReturnValue: Bool = true @@ -898,6 +913,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func setCurrentLine( line: String, expectsReturnValue: Bool = true @@ -915,6 +931,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func delCurrentLine( expectsReturnValue: Bool = true ) -> Nvim.Response { @@ -952,6 +969,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func setVar( name: String, value: Nvim.Value, @@ -971,6 +989,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func delVar( name: String, expectsReturnValue: Bool = true @@ -1030,6 +1049,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func setOption( name: String, value: Nvim.Value, @@ -1049,6 +1069,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func outWrite( str: String, expectsReturnValue: Bool = true @@ -1066,6 +1087,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func errWrite( str: String, expectsReturnValue: Bool = true @@ -1083,6 +1105,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func errWriteln( str: String, expectsReturnValue: Bool = true @@ -1140,6 +1163,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func setCurrentBuf( buffer: Nvim.Buffer, expectsReturnValue: Bool = true @@ -1197,6 +1221,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func setCurrentWin( window: Nvim.Window, expectsReturnValue: Bool = true @@ -1254,6 +1279,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func setCurrentTabpage( tabpage: Nvim.Tabpage, expectsReturnValue: Bool = true @@ -1271,6 +1297,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func subscribe( event: String, expectsReturnValue: Bool = true @@ -1288,6 +1315,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func unsubscribe( event: String, expectsReturnValue: Bool = true @@ -1470,6 +1498,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func winSetCursor( window: Nvim.Window, pos: [Int], @@ -1510,6 +1539,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func winSetHeight( window: Nvim.Window, height: Int, @@ -1550,6 +1580,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func winSetWidth( window: Nvim.Window, width: Int, @@ -1592,6 +1623,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func winSetVar( window: Nvim.Window, name: String, @@ -1613,6 +1645,7 @@ public extension Nvim { return .success(()) } + @discardableResult public func winDelVar( window: Nvim.Window, name: String, @@ -1655,6 +1688,7 @@ public extension Nvim { return .success(result) } + @discardableResult public func winSetOption( window: Nvim.Window, name: String, diff --git a/SwiftNeoVim/NeoVimAgent.h b/SwiftNeoVim/NeoVimAgent.h index 36ceef58..fb2e64fa 100644 --- a/SwiftNeoVim/NeoVimAgent.h +++ b/SwiftNeoVim/NeoVimAgent.h @@ -48,8 +48,6 @@ NS_ASSUME_NONNULL_BEGIN - (NSString * _Nullable)escapedFileName:(NSString *)fileName; - (NSArray *)escapedFileNames:(NSArray *)fileNames; -//- (NSArray *)buffers; -- (NSArray *)tabs; - (void)scrollHorizontal:(NSInteger)horiz vertical:(NSInteger)vert at:(Position)position; - (void)selectWindow:(NeoVimWindow *)window; diff --git a/SwiftNeoVim/NeoVimAgent.m b/SwiftNeoVim/NeoVimAgent.m index 11cbf1b9..c74e98ec 100644 --- a/SwiftNeoVim/NeoVimAgent.m +++ b/SwiftNeoVim/NeoVimAgent.m @@ -373,26 +373,6 @@ static CFDataRef local_server_callback(CFMessagePortRef local __unused, SInt32 m return [NSKeyedUnarchiver unarchiveObjectWithData:response]; } -//- (NSArray *)buffers { -// NSData *response = [self sendMessageWithId:NeoVimAgentMsgIdGetBuffers data:nil expectsReply:YES]; -// if (response == nil) { -// log4Warn("The response for the msg %ld was nil.", (long) NeoVimAgentMsgIdGetBuffers); -// return @[]; -// } -// -// return [NSKeyedUnarchiver unarchiveObjectWithData:response]; -//} - -- (NSArray *)tabs { - NSData *response = [self sendMessageWithId:NeoVimAgentMsgIdGetTabs data:nil expectsReply:YES]; - if (response == nil) { - log4Warn("The response for the msg %ld was nil.", (long) NeoVimAgentMsgIdGetTabs); - return @[]; - } - - return [NSKeyedUnarchiver unarchiveObjectWithData:response]; -} - - (void)runLocalServer { @autoreleasepool { CFMessagePortContext localContext = { diff --git a/SwiftNeoVim/NeoVimView+Api.swift b/SwiftNeoVim/NeoVimView+Api.swift index 1dded423..b8afbe9b 100644 --- a/SwiftNeoVim/NeoVimView+Api.swift +++ b/SwiftNeoVim/NeoVimView+Api.swift @@ -41,13 +41,22 @@ extension NeoVimView { return self.currentBuffer()?.isDirty ?? false } + public func allTabs() -> [NeoVimTab] { + let curBuf = self.nvim.checkBlocked { self.nvim.getCurrentBuf() }.value + let curTab = self.nvim.checkBlocked { self.nvim.getCurrentTabpage() }.value + + return self.nvim.checkBlocked({ nvim.listTabpages() }) + .value? + .flatMap { self.neoVimTab(for: $0, currentTabpage: curTab, currentBuffer: curBuf) } ?? [] + } + public func newTab() { self.exec(command: "tabe") } public func `open`(urls: [URL]) { - let tabs = self.agent.tabs() - let buffers = self.allBuffers() + let tabs = self.allTabs() + let buffers = tabs.map { $0.windows }.flatMap { $0 }.map { $0.buffer } let currentBufferIsTransient = buffers.first { $0.isCurrent }?.isTransient ?? false urls.enumerated().forEach { (idx, url) in @@ -85,7 +94,7 @@ extension NeoVimView { } public func select(buffer: NeoVimBuffer) { - for window in self.agent.tabs().map({ $0.windows }).flatMap({ $0 }) { + for window in self.allTabs().map({ $0.windows }).flatMap({ $0 }) { if window.buffer.handle == buffer.handle { self.agent.select(window) return @@ -191,6 +200,36 @@ extension NeoVimView { return NeoVimBuffer(handle: buf.handle, unescapedPath: path, dirty: dirty, readOnly: readonly, current: current) } + + private func neoVimWindow(for window: Nvim.Window, + currentWindow: Nvim.Window?, + currentBuffer: Nvim.Buffer?) -> NeoVimWindow? { + + guard let buf = self.nvim.checkBlocked({ self.nvim.winGetBuf(window: window) }).value else { + return nil + } + + guard let buffer = self.neoVimBuffer(for: buf, currentBuffer: currentBuffer) else { + return nil + } + + return NeoVimWindow(handle: window.handle, buffer: buffer, currentInTab: window == currentWindow) + } + + private func neoVimTab(for tabpage: Nvim.Tabpage, + currentTabpage: Nvim.Tabpage?, + currentBuffer: Nvim.Buffer?) -> NeoVimTab? { + + let curWinInTab = self.nvim.checkBlocked { self.nvim.tabpageGetWin(tabpage: tabpage) }.value + + let windows: [NeoVimWindow] = self.nvim.checkBlocked { self.nvim.tabpageListWins(tabpage: tabpage) } + .value? + .flatMap { self.neoVimWindow(for: $0, + currentWindow: curWinInTab, + currentBuffer: currentBuffer) } ?? [] + + return NeoVimTab(handle: tabpage.handle, windows: windows, current: tabpage == currentTabpage) + } } fileprivate let neoVimQuitTimeout = TimeInterval(5) diff --git a/SwiftNeoVim/NeoVimView+TouchBar.swift b/SwiftNeoVim/NeoVimView+TouchBar.swift index 3728d203..cbcba151 100644 --- a/SwiftNeoVim/NeoVimView+TouchBar.swift +++ b/SwiftNeoVim/NeoVimView+TouchBar.swift @@ -53,7 +53,7 @@ extension NeoVimView : NSTouchBarDelegate, NSScrubberDataSource, NSScrubberDeleg func updateTouchBarCurrentBuffer() { guard let tabsControl = getTabsControl() else { return } - tabsCache = self.agent.tabs() + tabsCache = self.allTabs() tabsControl.reloadData() (tabsControl.scrubberLayout as! NSScrubberProportionalLayout).numberOfVisibleItems = tabsControl.numberOfItems > 0 ? tabsControl.numberOfItems : 1 tabsControl.selectedIndex = selectedTabIndex() @@ -61,7 +61,7 @@ extension NeoVimView : NSTouchBarDelegate, NSScrubberDataSource, NSScrubberDeleg func updateTouchBarTab() { guard let tabsControl = getTabsControl() else { return } - tabsCache = self.agent.tabs() + tabsCache = self.allTabs() tabsControl.reloadData() tabsControl.selectedIndex = selectedTabIndex() } diff --git a/bin/generate_api_methods.py b/bin/generate_api_methods.py index 1386f52c..0f3b3da6 100755 --- a/bin/generate_api_methods.py +++ b/bin/generate_api_methods.py @@ -9,6 +9,7 @@ import os void_func_template = Template('''\ + @discardableResult public func ${func_name}(${args} expectsReturnValue: Bool = true ) -> Nvim.Response {