       .subscribeOn(self.scheduler)
   }
 
-  public func openInNewTab(urls: [URL]) -> Completable {
-    return Completable
+  func openInNewTab(urls: [URL]) -> Completable {
+    Completable
       .concat(urls.map { url in self.open(url, cmd: "tabe") })
       .subscribeOn(self.scheduler)
   }
 
-  public func openInCurrentTab(url: URL) -> Completable {
-    return self.open(url, cmd: "e")
-  }
-
-  public func openInHorizontalSplit(urls: [URL]) -> Completable {
-    return Completable
+  func openInCurrentTab(url: URL) -> Completable {
+    self.open(url, cmd: "e")
+  }
+
+  func openInHorizontalSplit(urls: [URL]) -> Completable {
+    Completable
       .concat(urls.map { url in self.open(url, cmd: "sp") })
       .subscribeOn(self.scheduler)
   }
 
-  public func openInVerticalSplit(urls: [URL]) -> Completable {
-    return Completable
+  func openInVerticalSplit(urls: [URL]) -> Completable {
+    Completable
       .concat(urls.map { url in self.open(url, cmd: "vsp") })
       .subscribeOn(self.scheduler)
   }
 
-  public func select(buffer: NvimView.Buffer) -> Completable {
-    return self
+  func select(buffer: NvimView.Buffer) -> Completable {
+    self
       .allTabs()
-      .map { tabs in tabs.map { $0.windows }.flatMap { $0 } }
+      .map { tabs in tabs.map(\.windows).flatMap { $0 } }
       .flatMapCompletable { wins -> Completable in
         if let win = wins.first(where: { $0.buffer == buffer }) {
           return self.api.setCurrentWin(window: RxNeovimApi.Window(win.handle))

              let dirty = info["modified"]?.boolValue,
              let buftype = info["buftype"]?.stringValue,
              let listed = info["buflisted"]?.boolValue
          else {
          throw RxNeovimApi.Error.exception(message: "Could not convert values from the dictionary.")
        }

        let url = path == "" || buftype != "" ? nil : URL(fileURLWithPath: path)

        return NvimView.Buffer(apiBuffer: buf,
                               url: url,
                               type: buftype,
                               isDirty: dirty,
                               isCurrent: current,
                               isListed: listed)
      }
      .subscribeOn(self.scheduler)
  }

  private func `open`(_ url: URL, cmd: String) -> Completable {
    return self.api
      .command(command: "\(cmd) \(url.path)")
      .subscribeOn(self.scheduler)
  }

  private func neoVimWindow(for window: RxNeovimApi.Window,
                            currentWindow: RxNeovimApi.Window?,
                            currentBuffer: RxNeovimApi.Buffer?) -> Single<NvimView.Window> {

    return self.api
      .winGetBuf(window: window)
      .flatMap { buf in self.neoVimBuffer(for: buf, currentBuffer: currentBuffer) }
      .map { buffer in NvimView.Window(apiWindow: window, buffer: buffer, isCurrentInTab: window == currentWindow) }
  }

  private func neoVimTab(for tabpage: RxNeovimApi.Tabpage,
                         currentTabpage: RxNeovimApi.Tabpage?,
                         currentBuffer: RxNeovimApi.Buffer?) -> Single<NvimView.Tabpage> {

    return Single.zip(
        self.api.tabpageGetWin(tabpage: tabpage),
        self.api.tabpageListWins(tabpage: tabpage)) { (curWin: $0, wins: $1) }
      .map { tuple in
        tuple.wins.map { win in
          return self.neoVimWindow(for: win, currentWindow: tuple.curWin, currentBuffer: currentBuffer)
        }
      }
      .flatMap(Single.fromSinglesToSingleOfArray)
      .map { wins in NvimView.Tabpage(apiTabpage: tabpage, windows: wins, isCurrent: tabpage == currentTabpage) }
  }
}

      .subscribeOn(self.scheduler)
  }

  func goTo(line: Int) -> Completable {
    self.api.command(command: "\(line)")
  }

  /// Closes the current window.
  func closeCurrentTab() -> Completable {
    self.api
      .command(command: "q")
      .subscribeOn(self.scheduler)
  }

  func saveCurrentTab() -> Completable {
    self.api
      .command(command: "w")
      .subscribeOn(self.scheduler)
  }

  func saveCurrentTab(url: URL) -> Completable {
    self.api
      .command(command: "w \(url.path)")
      .subscribeOn(self.scheduler)
  }

  func closeCurrentTabWithoutSaving() -> Completable {
    self.api
      .command(command: "q!")
      .subscribeOn(self.scheduler)
  }

  func quitNeoVimWithoutSaving() -> Completable {
    self.api
      .command(command: "qa!")
      .subscribeOn(self.scheduler)
  }

  func vimOutput(of command: String) -> Single<String> {
    self.api
      .exec(src: command, output: true)
      .subscribeOn(self.scheduler)
  }

  func cursorGo(to position: Position) -> Completable {
    self.api
      .getCurrentWin()
      .flatMapCompletable { curWin in
        self.api.winSetCursor(window: curWin, pos: [position.row, position.column])
      }
      .subscribeOn(self.scheduler)
  }

  func didBecomeMain() -> Completable { self.bridge.focusGained(true) }

  func didResignMain() -> Completable { self.bridge.focusGained(false) }

  internal func neoVimBuffer(
    for buf: RxNeovimApi.Buffer,
    currentBuffer: RxNeovimApi.Buffer?
  ) -> Single<NvimView.Buffer> {
    self.api
      .bufGetInfo(buffer: buf)
      .map { info -> NvimView.Buffer in
        let current = buf == currentBuffer
