1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-24 22:33:52 +03:00

Format VimR folder with swiftformat

This commit is contained in:
Tae Won Ha 2020-11-19 21:14:36 +01:00
parent ed05f433c9
commit ac5d0ca055
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
63 changed files with 1013 additions and 935 deletions

View File

@ -6,7 +6,6 @@
import Foundation
class AdvancedPrefReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = AdvancedPref.Action
@ -14,7 +13,6 @@ class AdvancedPrefReducer: ReducerType {
var state = pair.state
switch pair.action {
case let .setUseLiveResize(value):
state.mainWindowTemplate.useLiveResize = value
state.mainWindows.keys.forEach { state.mainWindows[$0]?.useLiveResize = value }

View File

@ -8,11 +8,9 @@ import PureLayout
import RxSwift
class AdvancedPref: PrefPane, UiComponent, NSTextFieldDelegate {
typealias StateType = AppState
enum Action {
case setUseInteractiveZsh(Bool)
case setUseSnapshotUpdate(Bool)
case setTrackpadScrollResistance(Double)
@ -21,11 +19,11 @@ class AdvancedPref: PrefPane, UiComponent, NSTextFieldDelegate {
}
override var displayName: String {
return "Advanced"
"Advanced"
}
override var pinToContainer: Bool {
return true
true
}
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
@ -46,10 +44,10 @@ class AdvancedPref: PrefPane, UiComponent, NSTextFieldDelegate {
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
if self.useInteractiveZsh != state.mainWindowTemplate.useInteractiveZsh
|| self.useSnapshotUpdate != state.useSnapshotUpdate
|| self.useLiveResize != state.mainWindowTemplate.useLiveResize
|| self.drawsParallel != state.mainWindowTemplate.drawsParallel {
|| self.useSnapshotUpdate != state.useSnapshotUpdate
|| self.useLiveResize != state.mainWindowTemplate.useLiveResize
|| self.drawsParallel != state.mainWindowTemplate.drawsParallel
{
self.useInteractiveZsh = state.mainWindowTemplate.useInteractiveZsh
self.useSnapshotUpdate = state.useSnapshotUpdate
self.useLiveResize = state.mainWindowTemplate.useLiveResize
@ -76,7 +74,8 @@ class AdvancedPref: PrefPane, UiComponent, NSTextFieldDelegate {
private let drawsParallelCheckbox = NSButton(forAutoLayout: ())
private let sensitivitySlider = NSSlider(forAutoLayout: ())
required init?(coder: NSCoder) {
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -93,47 +92,55 @@ class AdvancedPref: PrefPane, UiComponent, NSTextFieldDelegate {
let paneTitle = self.paneTitleTextField(title: "Advanced")
let useInteractiveZsh = self.useInteractiveZshCheckbox
self.configureCheckbox(button: useInteractiveZsh,
title: "Use interactive mode for zsh",
action: #selector(AdvancedPref.useInteractiveZshAction(_:)))
self.configureCheckbox(
button: useInteractiveZsh,
title: "Use interactive mode for zsh",
action: #selector(AdvancedPref.useInteractiveZshAction(_:))
)
let useInteractiveZshInfo = self.infoTextField(markdown: #"""
If your login shell is `zsh`, when checked, the `-i` option will be used to launch `zsh`.\
Checking this option may break VimR if your `.zshrc` contains complex stuff.\
It may be a good idea to put the `PATH`-settings in `.zshenv` and let this unchecked.\
*Use with caution.*
"""#)
If your login shell is `zsh`, when checked, the `-i` option will be used to launch `zsh`.\
Checking this option may break VimR if your `.zshrc` contains complex stuff.\
It may be a good idea to put the `PATH`-settings in `.zshenv` and let this unchecked.\
*Use with caution.*
"""#)
let useSnapshotUpdate = self.useSnapshotUpdateCheckbox
self.configureCheckbox(button: self.useSnapshotUpdateCheckbox,
title: "Use Snapshot Update Channel",
action: #selector(AdvancedPref.useSnapshotUpdateChannelAction(_:)))
self.configureCheckbox(
button: self.useSnapshotUpdateCheckbox,
title: "Use Snapshot Update Channel",
action: #selector(AdvancedPref.useSnapshotUpdateChannelAction(_:))
)
let useSnapshotUpdateInfo = self.infoTextField(markdown: #"""
If you are adventurous, check this. You'll be test driving the newest snapshot builds\
of VimR in no time!
"""#)
If you are adventurous, check this. You'll be test driving the newest snapshot builds\
of VimR in no time!
"""#)
let useLiveResize = self.useLiveResizeCheckbox
self.configureCheckbox(button: useLiveResize,
title: "Use Live Window Resizing",
action: #selector(AdvancedPref.useLiveResizeAction(_:)))
self.configureCheckbox(
button: useLiveResize,
title: "Use Live Window Resizing",
action: #selector(AdvancedPref.useLiveResizeAction(_:))
)
let useLiveResizeInfo = self.infoTextField(markdown: #"""
The Live Resizing is yet experimental. You may experience some issues.\
If you do, please report them at [GitHub](https://github.com/qvacua/vimr/issues).
"""#)
The Live Resizing is yet experimental. You may experience some issues.\
If you do, please report them at [GitHub](https://github.com/qvacua/vimr/issues).
"""#)
let drawsParallelBox = self.drawsParallelCheckbox
self.configureCheckbox(button: drawsParallelBox,
title: "Use Concurrent Rendering",
action: #selector(AdvancedPref.drawParallelAction(_:)))
self.configureCheckbox(
button: drawsParallelBox,
title: "Use Concurrent Rendering",
action: #selector(AdvancedPref.drawParallelAction(_:))
)
let drawsParallelInfo = self.infoTextField(markdown: #"""
VimR can compute the glyphs concurrently. This may result in faster rendering,\
depending on the situation. It will definitely result in higher CPU usage, e.g.\
when scrolling very fast.
"""#)
VimR can compute the glyphs concurrently. This may result in faster rendering,\
depending on the situation. It will definitely result in higher CPU usage, e.g.\
when scrolling very fast.
"""#)
let sensitivityTitle = self.titleTextField(title: "Scroll Sensitivity:")
let sensitivity = self.sensitivitySlider
@ -142,9 +149,9 @@ when scrolling very fast.
sensitivity.target = self
sensitivity.action = #selector(sensitivitySliderAction)
let sensitivityInfo = self.infoTextField(markdown: #"""
Trackpad scroll sensitivity is yet experimental. You may experience some issues.\
If you do, please report them at [GitHub issue #572](https://github.com/qvacua/vimr/issues/572).
"""#)
Trackpad scroll sensitivity is yet experimental. You may experience some issues.\
If you do, please report them at [GitHub issue #572](https://github.com/qvacua/vimr/issues/572).
"""#)
// We set the value of the NSSlider only at the beginning.
self.sensitivitySlider.doubleValue = self.sensitivity
@ -156,7 +163,7 @@ If you do, please report them at [GitHub issue #572](https://github.com/qvacua/v
self.addSubview(useInteractiveZsh)
self.addSubview(useInteractiveZshInfo)
self.addSubview(sensitivityTitle)
self.addSubview(sensitivitySlider)
self.addSubview(self.sensitivitySlider)
self.addSubview(sensitivityInfo)
self.addSubview(useLiveResize)
self.addSubview(useLiveResizeInfo)
@ -174,7 +181,7 @@ If you do, please report them at [GitHub issue #572](https://github.com/qvacua/v
sensitivity.autoAlignAxis(.baseline, toSameAxisOf: sensitivityTitle)
sensitivity.autoPinEdge(.left, to: .right, of: sensitivityTitle, withOffset: 5)
sensitivityInfo.autoPinEdge(.top, to: .bottom, of: sensitivitySlider, withOffset: 5)
sensitivityInfo.autoPinEdge(.top, to: .bottom, of: self.sensitivitySlider, withOffset: 5)
sensitivityInfo.autoPinEdge(.left, to: .right, of: sensitivityTitle, withOffset: 5)
useLiveResize.autoPinEdge(.top, to: .bottom, of: sensitivityInfo, withOffset: 18)
@ -204,8 +211,8 @@ If you do, please report them at [GitHub issue #572](https://github.com/qvacua/v
}
// MARK: - Actions
extension AdvancedPref {
extension AdvancedPref {
@objc func useLiveResizeAction(_ sender: NSButton) {
self.emit(.setUseLiveResize(sender.boolState))
}

View File

@ -4,21 +4,19 @@
*/
import Cocoa
import RxSwift
import PureLayout
import Sparkle
import DictionaryCoding
import os
import Commons
import CommonsObjC
import DictionaryCoding
import os
import PureLayout
import RxSwift
import Sparkle
let debugMenuItemIdentifier = NSUserInterfaceItemIdentifier("debug-menu-item")
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
struct OpenConfig {
var urls: [URL]
var cwd: URL
@ -29,7 +27,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
}
enum Action {
case newMainWindow(config: OpenConfig)
case openInKeyWindow(config: OpenConfig)
@ -42,9 +39,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
var initialAppState: AppState
let dictDecoder = DictionaryDecoder()
if let stateDict = UserDefaults.standard.value(forKey: PrefMiddleware.compatibleVersion) as? [String: Any],
let state = try? dictDecoder.decode(AppState.self, from: stateDict) {
if let stateDict = UserDefaults.standard
.value(forKey: PrefMiddleware.compatibleVersion) as? [String: Any],
let state = try? dictDecoder.decode(AppState.self, from: stateDict)
{
initialAppState = state
} else {
initialAppState = .default
@ -113,8 +111,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
private var launching = true
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.general)
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.general)
private func setSparkleUrl(_ snapshot: Bool) {
if snapshot {
@ -130,27 +127,29 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
}
// MARK: - NSApplicationDelegate
extension AppDelegate {
extension AppDelegate {
func applicationWillFinishLaunching(_: Notification) {
self.launching = true
let appleEventManager = NSAppleEventManager.shared()
appleEventManager.setEventHandler(self,
andSelector: #selector(AppDelegate.handle(getUrlEvent:replyEvent:)),
forEventClass: UInt32(kInternetEventClass),
andEventID: UInt32(kAEGetURL))
appleEventManager.setEventHandler(
self,
andSelector: #selector(AppDelegate.handle(getUrlEvent:replyEvent:)),
forEventClass: UInt32(kInternetEventClass),
andEventID: UInt32(kAEGetURL)
)
}
func applicationDidFinishLaunching(_: Notification) {
self.launching = false
#if DEBUG
NSApp.mainMenu?.items.first { $0.identifier == debugMenuItemIdentifier }?.isHidden = false
NSApp.mainMenu?.items.first { $0.identifier == debugMenuItemIdentifier }?.isHidden = false
#endif
}
func applicationOpenUntitledFile(_ sender: NSApplication) -> Bool {
func applicationOpenUntitledFile(_: NSApplication) -> Bool {
if self.launching {
if self.openNewMainWindowOnLaunch {
self.newDocument(self)
@ -166,7 +165,7 @@ extension AppDelegate {
return false
}
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
func applicationShouldTerminate(_: NSApplication) -> NSApplication.TerminateReply {
self.context.savePrefs()
guard self.hasMainWindows else {
@ -210,7 +209,8 @@ extension AppDelegate {
func application(_ sender: NSApplication, openFiles filenames: [String]) {
let urls = filenames.map { URL(fileURLWithPath: $0) }
let config = OpenConfig(
urls: urls, cwd: FileUtils.userHomeUrl, cliPipePath: nil, nvimArgs: nil, envDict: nil, line: nil
urls: urls, cwd: FileUtils.userHomeUrl, cliPipePath: nil, nvimArgs: nil, envDict: nil,
line: nil
)
self.emit(.newMainWindow(config: config))
@ -226,37 +226,32 @@ extension AppDelegate {
}
// MARK: - AppleScript
extension AppDelegate {
@objc func handle(
getUrlEvent event: NSAppleEventDescriptor,
replyEvent _: NSAppleEventDescriptor
) {
guard let urlString = event.paramDescriptor(forKeyword: UInt32(keyDirectObject))?.stringValue
else { return }
@objc func handle(getUrlEvent event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
guard let urlString = event.paramDescriptor(forKeyword: UInt32(keyDirectObject))?.stringValue else {
return
}
guard let url = URL(string: urlString) else { return }
guard let url = URL(string: urlString) else {
return
}
guard url.scheme == "vimr" else { return }
guard url.scheme == "vimr" else {
return
}
guard let rawAction = url.host else { return }
guard let rawAction = url.host else {
return
}
guard let action = VimRUrlAction(rawValue: rawAction) else {
return
}
guard let action = VimRUrlAction(rawValue: rawAction) else { return }
let rawParams = url.query?.components(separatedBy: "&") ?? []
guard let pipePath = queryParam(pipePathPrefix, from: rawParams, transforming: identity).first else {
guard let pipePath = queryParam(pipePathPrefix, from: rawParams, transforming: identity).first
else {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = "Outdated Command Line Tool?"
alert.informativeText = "It seems that the installed vimr command line tool is outdated." +
"Please re-install it from the General Preferences."
"Please re-install it from the General Preferences."
alert.runModal()
return
@ -275,7 +270,7 @@ extension AppDelegate {
let envDict: [String: String]?
if let envPath = queryParam(envPathPrefix, from: rawParams, transforming: identity).first {
envDict = stringDict(from: URL(fileURLWithPath: envPath))
envDict = self.stringDict(from: URL(fileURLWithPath: envPath))
if FileManager.default.fileExists(atPath: envPath) {
do {
try FileManager.default.removeItem(atPath: envPath)
@ -287,45 +282,79 @@ extension AppDelegate {
envDict = nil
}
let line = queryParam(linePrefix, from: rawParams, transforming: { Int($0) }).compactMap { $0 }.first
let urls = queryParam(filePrefix, from: rawParams, transforming: { URL(fileURLWithPath: $0) })
let cwd = queryParam(cwdPrefix,
from: rawParams,
transforming: { URL(fileURLWithPath: $0) }).first ?? FileUtils.userHomeUrl
let wait = queryParam(waitPrefix, from: rawParams, transforming: { $0 == "true" ? true : false }).first ?? false
let line = self.queryParam(linePrefix, from: rawParams, transforming: { Int($0) })
.compactMap { $0 }.first
let urls = self.queryParam(
filePrefix,
from: rawParams,
transforming: { URL(fileURLWithPath: $0) }
)
let cwd = self.queryParam(
cwdPrefix,
from: rawParams,
transforming: { URL(fileURLWithPath: $0) }
).first ?? FileUtils.userHomeUrl
let wait = self.queryParam(
waitPrefix,
from: rawParams,
transforming: { $0 == "true" ? true : false }
).first ?? false
if wait == false {
_ = Darwin.close(Darwin.open(pipePath, O_WRONLY))
}
if wait == false { _ = Darwin.close(Darwin.open(pipePath, O_WRONLY)) }
// If we don't do this, the window is active, but not in front.
NSApp.activate(ignoringOtherApps: true)
switch action {
case .activate, .newWindow:
let config = OpenConfig(urls: urls, cwd: cwd, cliPipePath: pipePath, nvimArgs: nil, envDict: envDict, line: line)
let config = OpenConfig(
urls: urls,
cwd: cwd,
cliPipePath: pipePath,
nvimArgs: nil,
envDict: envDict,
line: line
)
self.emit(.newMainWindow(config: config))
case .open:
let config = OpenConfig(urls: urls, cwd: cwd, cliPipePath: pipePath, nvimArgs: nil, envDict: envDict, line: line)
let config = OpenConfig(
urls: urls,
cwd: cwd,
cliPipePath: pipePath,
nvimArgs: nil,
envDict: envDict,
line: line
)
self.emit(.openInKeyWindow(config: config))
case .separateWindows:
urls.forEach {
let config = OpenConfig(urls: [$0], cwd: cwd, cliPipePath: pipePath, nvimArgs: nil, envDict: nil, line: line)
let config = OpenConfig(
urls: [$0],
cwd: cwd,
cliPipePath: pipePath,
nvimArgs: nil,
envDict: nil,
line: line
)
self.emit(.newMainWindow(config: config))
}
case .nvim:
let config = OpenConfig(urls: urls,
cwd: cwd,
cliPipePath: pipePath,
nvimArgs: queryParam(nvimArgsPrefix, from: rawParams, transforming: identity),
envDict: envDict,
line: line)
let config = OpenConfig(
urls: urls,
cwd: cwd,
cliPipePath: pipePath,
nvimArgs: queryParam(
nvimArgsPrefix,
from: rawParams,
transforming: identity
),
envDict: envDict,
line: line
)
self.emit(.newMainWindow(config: config))
}
}
@ -345,9 +374,9 @@ extension AppDelegate {
private func queryParam<T>(_ prefix: String,
from rawParams: [String],
transforming transform: (String) -> T) -> [T] {
return rawParams
transforming transform: (String) -> T) -> [T]
{
rawParams
.filter { $0.hasPrefix(prefix) }
.compactMap { $0.without(prefix: prefix).removingPercentEncoding }
.map(transform)
@ -355,26 +384,22 @@ extension AppDelegate {
}
// MARK: - IBActions
extension AppDelegate {
extension AppDelegate {
@IBAction func checkForUpdates(_ sender: Any?) {
updater.checkForUpdates(sender)
}
@IBAction func newDocument(_ sender: Any?) {
@IBAction func newDocument(_: Any?) {
let config = OpenConfig(
urls: [], cwd: FileUtils.userHomeUrl, cliPipePath: nil, nvimArgs: nil, envDict: nil, line: nil
)
self.emit(.newMainWindow(config: config))
}
@IBAction func openInNewWindow(_ sender: Any?) {
self.openDocument(sender)
}
@IBAction func openInNewWindow(_ sender: Any?) { self.openDocument(sender) }
@IBAction func showPrefWindow(_ sender: Any?) {
self.emit(.preferences)
}
@IBAction func showPrefWindow(_: Any?) { self.emit(.preferences) }
// Invoked when no main window is open.
@IBAction func openDocument(_: Any?) {
@ -382,9 +407,7 @@ extension AppDelegate {
panel.canChooseDirectories = true
panel.allowsMultipleSelection = true
panel.begin { result in
guard result == .OK else {
return
}
guard result == .OK else { return }
let urls = panel.urls
let commonParentUrl = FileUtils.commonParent(of: urls)
@ -398,20 +421,21 @@ extension AppDelegate {
}
// MARK: - NSUserNotificationCenterDelegate
extension AppDelegate {
public func userNotificationCenter(_ center: NSUserNotificationCenter, shouldPresent _: NSUserNotification) -> Bool {
return true
}
extension AppDelegate {
func userNotificationCenter(
_: NSUserNotificationCenter,
shouldPresent _: NSUserNotification
) -> Bool { true }
}
// Keep the rawValues in sync with Action in the `vimr` Python script.
private enum VimRUrlAction: String {
case activate = "activate"
case open = "open"
case activate
case open
case newWindow = "open-in-new-window"
case separateWindows = "open-in-separate-windows"
case nvim = "nvim"
case nvim
}
private let updater = SUUpdater()

View File

@ -6,7 +6,6 @@
import Foundation
class AppDelegateReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = AppDelegate.Action
@ -18,7 +17,6 @@ class AppDelegateReducer: ReducerType {
var state = pair.state
switch pair.action {
case let .newMainWindow(config):
let mainWindow = self.newMainWindow(with: state, config: config)
state.mainWindows[mainWindow.uuid] = mainWindow
@ -30,7 +28,7 @@ class AppDelegateReducer: ReducerType {
break
}
state.mainWindows[uuid]?.urlsToOpen = config.urls.toDict { url in MainWindow.OpenMode.default }
state.mainWindows[uuid]?.urlsToOpen = config.urls.toDict { _ in MainWindow.OpenMode.default }
state.mainWindows[uuid]?.cwd = config.cwd
if let line = config.line {
state.mainWindows[uuid]?.goToLineFromCli = Marked(line)
@ -38,7 +36,6 @@ class AppDelegateReducer: ReducerType {
case .preferences:
state.preferencesOpen = Marked(true)
}
return (state, pair.action, true)
@ -46,8 +43,9 @@ class AppDelegateReducer: ReducerType {
private let baseServerUrl: URL
private func newMainWindow(with state: AppState, config: AppDelegate.OpenConfig) -> MainWindow.State {
private func newMainWindow(with state: AppState, config: AppDelegate.OpenConfig) -> MainWindow
.State
{
var mainWindow = state.mainWindowTemplate
mainWindow.uuid = UUID()
@ -77,7 +75,7 @@ class AppDelegateReducer: ReducerType {
}
private func frame(relativeTo refFrame: CGRect) -> CGRect {
return refFrame.offsetBy(dx: cascadeX, dy: -cascadeY)
refFrame.offsetBy(dx: cascadeX, dy: -cascadeY)
}
}

View File

@ -6,15 +6,11 @@
import Cocoa
import Down
extension NSView {
@objc var isFirstResponder: Bool { self.window?.firstResponder == self }
}
extension NSAttributedString {
static func infoLabel(markdown: String) -> NSAttributedString {
let down = Down(markdownString: markdown)
guard let result = try? down.toAttributedString(styler: downStyler) else {
@ -26,7 +22,6 @@ extension NSAttributedString {
}
extension NSTableView {
static func standardTableView() -> NSTableView {
let tableView = NSTableView(frame: CGRect.zero)
@ -53,7 +48,6 @@ extension NSTableView {
}
extension NSOutlineView {
static func standardOutlineView() -> NSOutlineView {
let outlineView = NSOutlineView(frame: CGRect.zero)
NSOutlineView.configure(toStandard: outlineView)
@ -99,18 +93,16 @@ extension NSOutlineView {
}
extension NSTextField {
static func defaultTitleTextField() -> NSTextField {
let field = NSTextField(forAutoLayout: ())
field.backgroundColor = NSColor.clear;
field.isEditable = false;
field.isBordered = false;
field.backgroundColor = NSColor.clear
field.isEditable = false
field.isBordered = false
return field
}
}
extension NSScrollView {
static func standardScrollView() -> NSScrollView {
let scrollView = NSScrollView(frame: CGRect.zero)
@ -124,8 +116,7 @@ extension NSScrollView {
}
}
private class AttributedStringMarkdownStyler {
private enum AttributedStringMarkdownStyler {
static func new() -> Styler {
let fonts = StaticFontCollection(
body: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize),
@ -138,7 +129,6 @@ private class AttributedStringMarkdownStyler {
}
private struct ParagraphStyles: ParagraphStyleCollection {
let heading1: NSParagraphStyle
let heading2: NSParagraphStyle
let heading3: NSParagraphStyle
@ -171,7 +161,6 @@ private struct ParagraphStyles: ParagraphStyleCollection {
}
}
private let fontCollection = StaticFontCollection(
body: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize),
code: NSFont.userFixedPitchFont(ofSize: NSFont.smallSystemFontSize)!

View File

@ -4,16 +4,14 @@
*/
import Cocoa
import NvimView
import PureLayout
import RxSwift
import NvimView
class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate, NSFontChanging {
typealias StateType = AppState
enum Action {
case setUsesColorscheme(Bool)
case setShowsFileIcon(Bool)
case setUsesLigatures(Bool)
@ -58,12 +56,12 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate
let appearance = state.mainWindowTemplate.appearance
guard self.font != appearance.font
|| self.linespacing != appearance.linespacing
|| self.characterspacing != appearance.characterspacing
|| self.usesLigatures != appearance.usesLigatures
|| self.usesColorscheme != appearance.usesTheme
|| self.showsFileIcon != appearance.showsFileIcon
else { return }
|| self.linespacing != appearance.linespacing
|| self.characterspacing != appearance.characterspacing
|| self.usesLigatures != appearance.usesLigatures
|| self.usesColorscheme != appearance.usesTheme
|| self.showsFileIcon != appearance.showsFileIcon
else { return }
self.font = appearance.font
self.linespacing = appearance.linespacing
@ -96,15 +94,16 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate
private let previewArea = NSTextView(frame: .zero)
private let exampleText = #"""
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789 -~ - ~
(){}[] +-*/= .,;:!?#&$%@|^
<- -> => >> << >>= =<< ..
:: -< >- -<< >>- ++ /= ==
"""#
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789 -~ - ~
(){}[] +-*/= .,;:!?#&$%@|^
<- -> => >> << >>= =<< ..
:: -< >- -<< >>- ++ /= ==
"""#
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func addViews() {
let paneTitle = self.paneTitleTextField(title: "Appearance")
@ -117,9 +116,9 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ
)
let useColorschemeInfo = self.infoTextField(markdown: #"""
If checked, the colors of the selected `colorscheme` will be used to render tools,\
for example the file browser.
"""#)
If checked, the colors of the selected `colorscheme` will be used to render tools,\
for example the file browser.
"""#)
let fileIcon = self.fileIconCheckbox
self.configureCheckbox(
@ -129,9 +128,9 @@ for example the file browser.
)
let fileIconInfo = self.infoTextField(markdown: #"""
In case the selected `colorscheme` does not play well with the file icons\
in the file browser and the buffer list, you can turn them off.
"""#)
In case the selected `colorscheme` does not play well with the file icons\
in the file browser and the buffer list, you can turn them off.
"""#)
let fontTitle = self.titleTextField(title: "Default Font:")
let fontPanelButton = self.fontPanelButton
@ -142,9 +141,9 @@ in the file browser and the buffer list, you can turn them off.
fontPanelButton.action = #selector(AppearancePref.showFontPanel(_:))
let fontInfo = self.infoTextField(markdown: #"""
The font panel will show variable width fonts, but VimR does not support them.\
If you select a variable width font, the rendering will be ... well ... questionable.
"""#)
The font panel will show variable width fonts, but VimR does not support them.\
If you select a variable width font, the rendering will be ... well ... questionable.
"""#)
let linespacingTitle = self.titleTextField(title: "Line Spacing:")
let linespacingField = self.linespacingField
@ -278,8 +277,9 @@ If you select a variable width font, the rendering will be ... well ... question
}
private func updateViews() {
sharedFontPanel.setPanelFont(font, isMultiple: false)
self.fontPanelButton.title = font.displayName.map { "\($0) \(font.pointSize)" } ?? "Show fonts..."
sharedFontPanel.setPanelFont(self.font, isMultiple: false)
self.fontPanelButton.title = self.font.displayName
.map { "\($0) \(font.pointSize)" } ?? "Show fonts..."
self.linespacingField.stringValue = String(format: "%.2f", self.linespacing)
self.characterspacingField.stringValue = String(format: "%.2f", self.characterspacing)
self.ligatureCheckbox.boolState = self.usesLigatures
@ -296,6 +296,7 @@ If you select a variable width font, the rendering will be ... well ... question
}
// MARK: - NSFontChanging
extension AppearancePref {
func changeFont(_ sender: NSFontManager?) {
guard let fontManager = sender else { return }
@ -306,8 +307,8 @@ extension AppearancePref {
}
// MARK: - Actions
extension AppearancePref {
extension AppearancePref {
@objc func usesColorschemeAction(_ sender: NSButton) {
self.emit(.setUsesColorscheme(sender.boolState))
}
@ -351,7 +352,6 @@ extension AppearancePref {
return cgfCharacterspacing
}
private func cappedFontSize(_ size: Int) -> CGFloat {
let cgfSize = size.cgf

View File

@ -6,7 +6,6 @@
import Foundation
class AppearancePrefReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = AppearancePref.Action
@ -15,7 +14,6 @@ class AppearancePrefReducer: ReducerType {
var appearance = state.mainWindowTemplate.appearance
switch pair.action {
case let .setUsesColorscheme(value):
appearance.usesTheme = value
@ -30,10 +28,9 @@ class AppearancePrefReducer: ReducerType {
case let .setLinespacing(linespacing):
appearance.linespacing = linespacing
case let .setCharacterspacing(characterspacing):
appearance.characterspacing = characterspacing
}
self.modify(state: &state, with: appearance)

View File

@ -7,7 +7,6 @@ import Cocoa
import Sparkle
class Application: NSApplication {
override init() {
setPressAndHoldSetting()
super.init()

View File

@ -4,21 +4,20 @@
*/
import Cocoa
import RxSwift
import PureLayout
import NvimView
import Commons
import NvimView
import PureLayout
import RxSwift
class BuffersList: NSView,
UiComponent,
NSTableViewDataSource,
NSTableViewDelegate,
ThemedView {
UiComponent,
NSTableViewDataSource,
NSTableViewDelegate,
ThemedView
{
typealias StateType = MainWindow.State
enum Action {
case open(NvimView.Buffer)
}
@ -50,7 +49,8 @@ class BuffersList: NSView,
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
if state.viewToBeFocused != nil,
case .bufferList = state.viewToBeFocused! {
case .bufferList = state.viewToBeFocused!
{
self.beFirstResponder()
}
@ -59,13 +59,15 @@ class BuffersList: NSView,
themeChanged: state.appearance.theme.mark != self.lastThemeMark,
usesTheme: state.appearance.usesTheme,
forTheme: { self.updateTheme(state.appearance.theme) },
forDefaultTheme: { self.updateTheme(Marked(Theme.default)) })
forDefaultTheme: { self.updateTheme(Marked(Theme.default)) }
)
self.usesTheme = state.appearance.usesTheme
if self.buffers == state.buffers
&& !themeChanged
&& self.showsFileIcon == state.appearance.showsFileIcon {
if self.buffers == state.buffers,
!themeChanged,
self.showsFileIcon == state.appearance.showsFileIcon
{
return
}
@ -87,7 +89,8 @@ class BuffersList: NSView,
private var buffers = [NvimView.Buffer]()
required init?(coder: NSCoder) {
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -109,11 +112,11 @@ class BuffersList: NSView,
}
// MARK: - Actions
extension BuffersList {
@objc func doubleClickAction(_ sender: Any?) {
extension BuffersList {
@objc func doubleClickAction(_: Any?) {
let clickedRow = self.bufferList.clickedRow
guard clickedRow >= 0 && clickedRow < self.buffers.count else {
guard clickedRow >= 0, clickedRow < self.buffers.count else {
return
}
@ -122,31 +125,33 @@ extension BuffersList {
}
// MARK: - NSTableViewDataSource
extension BuffersList {
extension BuffersList {
@objc(numberOfRowsInTableView:)
func numberOfRows(in tableView: NSTableView) -> Int {
return self.buffers.count
func numberOfRows(in _: NSTableView) -> Int {
self.buffers.count
}
}
// MARK: - NSTableViewDelegate
extension BuffersList {
extension BuffersList {
public func tableView(
_ tableView: NSTableView,
rowViewForRow row: Int
rowViewForRow _: Int
) -> NSTableRowView? {
return tableView.makeView(
tableView.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("buffer-row-view"),
owner: self
) as? ThemedTableRow ?? ThemedTableRow(withIdentifier: "buffer-row-view",
themedView: self)
) as? ThemedTableRow ?? ThemedTableRow(
withIdentifier: "buffer-row-view",
themedView: self
)
}
func tableView(
_ tableView: NSTableView,
viewFor tableColumn: NSTableColumn?,
viewFor _: NSTableColumn?,
row: Int
) -> NSView? {
let cachedCell = (tableView.makeView(
@ -169,13 +174,13 @@ extension BuffersList {
}
func tableView(
_ tableView: NSTableView,
_: NSTableView,
didAdd rowView: NSTableRowView,
forRow row: Int
forRow _: Int
) {
guard let cellWidth = (rowView.view(atColumn: 0) as? NSTableCellView)?
.fittingSize.width
else {
else {
return
}
@ -194,15 +199,17 @@ extension BuffersList {
}
let pathInfo = url.pathComponents
.dropFirst()
.dropLast()
.reversed()
.joined(separator: " / ") + " /"
.dropFirst()
.dropLast()
.reversed()
.joined(separator: " / ") + " /"
let rowText = NSMutableAttributedString(string: "\(name)\(pathInfo)")
rowText.addAttribute(NSAttributedString.Key.foregroundColor,
value: self.theme.foreground,
range: NSRange(location: 0, length: name.count))
rowText.addAttribute(
NSAttributedString.Key.foregroundColor,
value: self.theme.foreground,
range: NSRange(location: 0, length: name.count)
)
rowText.addAttribute(
NSAttributedString.Key.foregroundColor,

View File

@ -6,7 +6,6 @@
import Foundation
class BuffersListReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<BuffersList.Action>
@ -14,10 +13,8 @@ class BuffersListReducer: ReducerType {
var state = tuple.state
switch tuple.action.payload {
case let .open(buffer):
state.currentBufferToSet = buffer
}
return (state, tuple.action, true)

View File

@ -8,13 +8,11 @@ import RxSwift
typealias AnyAction = Any
extension ReduxTypes {
typealias StateType = AppState
typealias ActionType = AnyAction
}
class Context: ReduxContext {
// The following should only be used when Cmd-Q'ing
func savePrefs() { self.prefMiddleware.applyPref(from: self.state) }
@ -24,7 +22,7 @@ class Context: ReduxContext {
let markdownPreviewMiddleware = MarkdownPreviewMiddleware()
let markdownPreviewReducer = MarkdownPreviewReducer(baseServerUrl: baseServerUrl)
let htmlPreviewReducer = HtmlPreviewReducer(baseServerUrl: baseServerUrl)
let httpMiddleware: HttpServerMiddleware = HttpServerMiddleware(port: baseServerUrl.port!)
let httpMiddleware = HttpServerMiddleware(port: baseServerUrl.port!)
let uiRootReducer = UiRootReducer()
let openQuicklyReducer = OpenQuicklyReducer()
let rpcEpic = RpcAppearanceEpic(emitter: self.actionEmitter)
@ -52,7 +50,8 @@ class Context: ReduxContext {
self.prefMiddleware.mainWindow.apply,
self.prefMiddleware.apply,
rpcEpic.apply,
])
]
)
.filter { $0.modified }
.subscribe(onNext: self.emitAppState)
.disposed(by: self.disposeBag)

View File

@ -3,15 +3,13 @@
* See LICENSE
*/
import Foundation
import CoreData
import os
import Commons
import CoreData
import Foundation
import os
class CoreDataStack {
enum Error: Swift.Error {
case noCacheFolder
case pathDoesNotExit
case pathNotFolder
@ -20,7 +18,6 @@ class CoreDataStack {
}
enum StoreLocation {
case temp(String)
case cache(String)
case path(String)
@ -45,15 +42,14 @@ class CoreDataStack {
let fileManager = FileManager.default
let url: URL
switch storeLocation {
case .temp(let folderName):
case let .temp(folderName):
let parentUrl = fileManager
.temporaryDirectory
.appendingPathComponent(folderName)
try fileManager.createDirectory(at: parentUrl, withIntermediateDirectories: true)
url = parentUrl.appendingPathComponent(modelName)
case .cache(let folderName):
case let .cache(folderName):
guard let cacheUrl = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first else {
throw Error.noCacheFolder
}
@ -62,14 +58,13 @@ class CoreDataStack {
url = parentUrl.appendingPathComponent(modelName)
case .path(let path):
case let .path(path):
guard fileManager.fileExists(atPath: path) else { throw Error.pathDoesNotExit }
let parentFolder = URL(fileURLWithPath: path)
guard parentFolder.isDir else { throw Error.pathNotFolder }
url = parentFolder.appendingPathComponent(modelName)
}
self.container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: url)]

View File

@ -6,7 +6,6 @@
import Cocoa
class CssUtils {
static let cssOverridesTemplate: String = try! String(
contentsOf: Resources.cssOverridesTemplateUrl
)
@ -15,22 +14,36 @@ class CssUtils {
self
.cssOverridesTemplate
.replacingOccurrences(of: "{{ nvim-color }}", with: self.htmlColor(theme.cssColor))
.replacingOccurrences(of: "{{ nvim-background-color }}",
with: self.htmlColor(theme.cssBackgroundColor))
.replacingOccurrences(
of: "{{ nvim-background-color }}",
with: self.htmlColor(theme.cssBackgroundColor)
)
.replacingOccurrences(of: "{{ nvim-a }}", with: self.htmlColor(theme.cssA))
.replacingOccurrences(of: "{{ nvim-hr-background-color }}",
with: self.htmlColor(theme.cssHrBorderBackgroundColor))
.replacingOccurrences(of: "{{ nvim-hr-border-bottom-color }}",
with: self.htmlColor(theme.cssHrBorderBottomColor))
.replacingOccurrences(of: "{{ nvim-blockquote-border-left-color }}",
with: self.htmlColor(theme.cssBlockquoteBorderLeftColor))
.replacingOccurrences(of: "{{ nvim-blockquote-color }}",
with: self.htmlColor(theme.cssBlockquoteColor))
.replacingOccurrences(of: "{{ nvim-h2-border-bottom-color }}",
with: self.htmlColor(theme.cssH2BorderBottomColor))
.replacingOccurrences(
of: "{{ nvim-hr-background-color }}",
with: self.htmlColor(theme.cssHrBorderBackgroundColor)
)
.replacingOccurrences(
of: "{{ nvim-hr-border-bottom-color }}",
with: self.htmlColor(theme.cssHrBorderBottomColor)
)
.replacingOccurrences(
of: "{{ nvim-blockquote-border-left-color }}",
with: self.htmlColor(theme.cssBlockquoteBorderLeftColor)
)
.replacingOccurrences(
of: "{{ nvim-blockquote-color }}",
with: self.htmlColor(theme.cssBlockquoteColor)
)
.replacingOccurrences(
of: "{{ nvim-h2-border-bottom-color }}",
with: self.htmlColor(theme.cssH2BorderBottomColor)
)
.replacingOccurrences(of: "{{ nvim-h6-color }}", with: self.htmlColor(theme.cssH6Color))
.replacingOccurrences(of: "{{ nvim-code-background-color }}",
with: self.htmlColor(theme.cssCodeBackgroundColor))
.replacingOccurrences(
of: "{{ nvim-code-background-color }}",
with: self.htmlColor(theme.cssCodeBackgroundColor)
)
.replacingOccurrences(of: "{{ nvim-code-color }}", with: self.htmlColor(theme.cssCodeColor))
}

View File

@ -7,7 +7,6 @@ import Foundation
import RxSwift
class Debouncer<T> {
let observable: Observable<T>
init(interval: RxTimeInterval) {

View File

@ -7,11 +7,9 @@ import Foundation
import WebKit
struct Defs {
static let loggerSubsystem = Bundle.main.bundleIdentifier!
struct LoggerCategory {
enum LoggerCategory {
static let general = "general"
static let ui = "ui"

View File

@ -4,19 +4,18 @@
*/
import Cocoa
import RxSwift
import PureLayout
import MaterialIcons
import Commons
import MaterialIcons
import PureLayout
import RxSwift
import Workspace
class FileBrowser: NSView,
UiComponent {
UiComponent
{
typealias StateType = MainWindow.State
enum Action {
case open(url: URL, mode: MainWindow.OpenMode)
case setAsWorkingDirectory(URL)
case setShowHidden(Bool)
@ -41,8 +40,8 @@ class FileBrowser: NSView,
action: #selector(FileBrowser.showHiddenAction),
keyEquivalent: ""
)
showHiddenMenuItem.boolState = state.fileBrowserShowHidden
self.menuItems = [showHiddenMenuItem]
self.showHiddenMenuItem.boolState = state.fileBrowserShowHidden
self.menuItems = [self.showHiddenMenuItem]
super.init(frame: .zero)
@ -78,7 +77,8 @@ class FileBrowser: NSView,
private var cwd: URL
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func addViews() {
let scrollView = NSScrollView.standardScrollView()
@ -91,9 +91,7 @@ class FileBrowser: NSView,
}
extension FileBrowser {
class InnerCustomToolbar: CustomToolBar {
let goToParentButton = NSButton(forAutoLayout: ())
let scrollToSourceButton = NSButton(forAutoLayout: ())
let refreshButton = NSButton(forAutoLayout: ())
@ -174,30 +172,31 @@ extension FileBrowser {
)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
}
// MARK: - Actions
extension FileBrowser {
extension FileBrowser {
@objc func showHiddenAction(_ sender: Any?) {
guard let menuItem = sender as? NSMenuItem else { return }
self.emit(UuidAction(uuid: self.uuid, action: .setShowHidden(!menuItem.boolState)))
}
@objc func goToParentAction(_ sender: Any?) {
@objc func goToParentAction(_: Any?) {
self.emit(UuidAction(uuid: self.uuid, action: .setAsWorkingDirectory(self.cwd.parent)))
}
@objc func scrollToSourceAction(_ sender: Any?) {
@objc func scrollToSourceAction(_: Any?) {
guard let url = self.currentBufferUrl else { return }
self.fileView.select(url)
}
@objc func refreshAction(_ sender: Any?) {
@objc func refreshAction(_: Any?) {
self.emit(UuidAction(uuid: self.uuid, action: .refresh))
}
}

View File

@ -6,7 +6,6 @@
import Foundation
class FileBrowserReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<FileBrowser.Action>
@ -14,7 +13,6 @@ class FileBrowserReducer: ReducerType {
var state = tuple.state
switch tuple.action.payload {
case let .open(url, mode):
state.urlsToOpen[url] = mode
state.viewToBeFocused = .neoVimView
@ -27,7 +25,6 @@ class FileBrowserReducer: ReducerType {
case .refresh:
state.lastFileSystemUpdate = Marked(state.cwd)
}
return (state, tuple.action, true)

View File

@ -3,22 +3,21 @@
* See LICENSE
*/
import Foundation
import EonilFSEvents
import os
import Commons
import EonilFSEvents
import Foundation
import os
class FileMonitor {
static let fileSystemEventsLatency = 1.0
private(set) var urlToMonitor = FileUtils.userHomeUrl
func monitor(url: URL, eventHandler: (@escaping (URL) -> Void)) throws {
func monitor(url: URL, eventHandler: @escaping (URL) -> Void) throws {
self.stopMonitor()
self.urlToMonitor = url
self.monitor = try EonilFSEventStream(
pathsToWatch: [urlToMonitor.path],
pathsToWatch: [self.urlToMonitor.path],
sinceWhen: EonilFSEventsEventID.getCurrentEventId(),
latency: FileMonitor.fileSystemEventsLatency,
flags: [],

View File

@ -4,18 +4,18 @@
*/
import Cocoa
import Commons
import MaterialIcons
import NvimView
import os
import PureLayout
import RxSwift
import MaterialIcons
import os
import Commons
class FileOutlineView: NSOutlineView,
UiComponent,
NSOutlineViewDelegate,
ThemedView {
UiComponent,
NSOutlineViewDelegate,
ThemedView
{
typealias StateType = MainWindow.State
@objc dynamic var content = [Node]()
@ -150,7 +150,8 @@ class FileOutlineView: NSOutlineView,
self.unbind(.selectionIndexPaths)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func handleFileSystemChanges(_ changedUrl: URL) {
DispatchQueue.main.async {
@ -206,7 +207,7 @@ class FileOutlineView: NSOutlineView,
self.treeController.preservesSelection = true
self.treeController.sortDescriptors = [
NSSortDescriptor(key: "isLeaf", ascending: true), // Folders first,
NSSortDescriptor(key: "displayName", ascending: true) // then, name
NSSortDescriptor(key: "displayName", ascending: true), // then, name
]
// The following will create a retain cycle. The superview *must* unbind
@ -217,7 +218,7 @@ class FileOutlineView: NSOutlineView,
self.bind(.selectionIndexPaths, to: self.treeController, withKeyPath: "selectionIndexPaths")
}
private func changedTreeNode(`for` url: URL) -> NSTreeNode? {
private func changedTreeNode(for url: URL) -> NSTreeNode? {
if url == self.cwd { return self.treeController.arrangedObjects }
let cwdCompsCount = self.cwd.pathComponents.count
@ -226,12 +227,12 @@ class FileOutlineView: NSOutlineView,
let rootTreeNode = self.treeController.arrangedObjects
let changedTreeNode = comps.reduce(rootTreeNode) { prev, comp in
prev.children?.first { child in return child.node?.displayName == comp } ?? prev
prev.children?.first { child in child.node?.displayName == comp } ?? prev
}
guard let changeNode = changedTreeNode.node else { return nil }
guard changeNode.url == url && changeNode.children != nil else { return nil }
guard changeNode.url == url, changeNode.children != nil else { return nil }
return changedTreeNode
}
@ -256,12 +257,12 @@ class FileOutlineView: NSOutlineView,
guard self.treeController.isEditable else { return }
let indexPathsToRemove = changeTreeNode
.children?
.filter { child in
guard let url = child.node?.url else { return true }
return newChildUrls.contains(url) == false
}
.map { $0.indexPath } ?? []
.children?
.filter { child in
guard let url = child.node?.url else { return true }
return newChildUrls.contains(url) == false
}
.map(\.indexPath) ?? []
changeTreeNode
.children?
@ -276,7 +277,7 @@ class FileOutlineView: NSOutlineView,
private func childUrls(for url: URL) -> [URL] {
let urls = FileUtils.directDescendants(of: url).sorted { lhs, rhs in
return lhs.lastPathComponent < rhs.lastPathComponent
lhs.lastPathComponent < rhs.lastPathComponent
}
if self.isShowHidden { return urls }
@ -345,8 +346,8 @@ class FileOutlineView: NSOutlineView,
}
// MARK: - Actions
extension FileOutlineView {
extension FileOutlineView {
@IBAction func doubleClickAction(_: Any?) {
let clickedTreeNode = self.clickedItem
guard let node = self.node(from: clickedTreeNode) else { return }
@ -392,9 +393,9 @@ extension FileOutlineView {
}
// MARK: - NSOutlineViewDelegate
extension FileOutlineView {
func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? {
extension FileOutlineView {
func outlineView(_: NSOutlineView, rowViewForItem _: Any) -> NSTableRowView? {
let view = self.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("file-row-view"),
owner: self
@ -403,7 +404,7 @@ extension FileOutlineView {
return view
}
func outlineView(_: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
func outlineView(_: NSOutlineView, viewFor _: NSTableColumn?, item: Any) -> NSView? {
guard let node = self.node(from: item) else { return nil }
let cellView = self.makeView(
@ -422,9 +423,9 @@ extension FileOutlineView {
return cellView
}
func outlineView(_: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat { 20 }
func outlineView(_: NSOutlineView, heightOfRowByItem _: Any) -> CGFloat { 20 }
func outlineView(_ outlineView: NSOutlineView, shouldExpandItem item: Any) -> Bool {
func outlineView(_: NSOutlineView, shouldExpandItem item: Any) -> Bool {
guard let node = self.node(from: item) else { return false }
if node.isChildrenScanned { return true }
@ -434,7 +435,7 @@ extension FileOutlineView {
return true
}
func outlineView(_ outlineView: NSOutlineView, didAdd rowView: NSTableRowView, forRow row: Int) {
func outlineView(_: NSOutlineView, didAdd rowView: NSTableRowView, forRow row: Int) {
guard let cellWidth = (rowView.view(atColumn: 0) as? NSTableCellView)?.fittingSize.width else {
return
}
@ -442,7 +443,7 @@ extension FileOutlineView {
let level = self.level(forRow: row).cgf
let width = level * self.indentationPerLevel + cellWidth + columnWidthRightPadding
self.cachedColumnWidth = max(self.cachedColumnWidth, width)
self.tableColumns[0].width = cachedColumnWidth
self.tableColumns[0].width = self.cachedColumnWidth
let rv = rowView as? ThemedTableRow
guard rv?.themeToken != self.lastThemeMark else { return }
@ -455,20 +456,20 @@ extension FileOutlineView {
}
// MARK: - NSUserInterfaceValidations
extension FileOutlineView {
extension FileOutlineView {
override func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
guard let clickedNode = self.node(from: self.clickedItem) else { return true }
if item.action == #selector(setAsWorkingDirectory(_:)) { return clickedNode.url.isDir }
if item.action == #selector(self.setAsWorkingDirectory(_:)) { return clickedNode.url.isDir }
return true
}
}
// MARK: - NSView
extension FileOutlineView {
extension FileOutlineView {
override func keyDown(with event: NSEvent) {
guard let char = event.charactersIgnoringModifiers?.first else {
super.keyDown(with: event)
@ -495,8 +496,7 @@ extension FileOutlineView {
}
class Node: NSObject, Comparable {
static func <(lhs: Node, rhs: Node) -> Bool { lhs.displayName < rhs.displayName }
static func < (lhs: Node, rhs: Node) -> Bool { lhs.displayName < rhs.displayName }
@objc dynamic var url: URL
@objc dynamic var isLeaf: Bool
@ -521,7 +521,6 @@ class Node: NSObject, Comparable {
}
private extension NSTreeNode {
var node: Node? { self.representedObject as? Node }
}

View File

@ -7,6 +7,5 @@ import Foundation
import os
extension URL {
var direntType: UInt8 { (self as NSURL).direntType() }
}

View File

@ -7,7 +7,6 @@ import Foundation
import os
class FuzzyMatcherPool {
let pattern: String
init(pattern: String, initialPoolSize: Int = 2) {
@ -17,7 +16,7 @@ class FuzzyMatcherPool {
}
func request() -> FuzzyMatcher {
return self.lock.withLock {
self.lock.withLock {
if self.matchers.isEmpty {
let matcher = FuzzyMatcher(pattern: self.pattern)
return matcher
@ -45,7 +44,6 @@ class FuzzyMatcherPool {
}
private extension NSLocking {
func withLock<T>(_ body: () -> T) -> T {
self.lock()
defer { self.unlock() }

View File

@ -3,13 +3,12 @@
* See LICENSE
*/
import Foundation
import CoreData
import os
import Commons
import CoreData
import Foundation
import os
class FuzzySearchService {
typealias ScoredUrlsCallback = ([ScoredUrl]) -> Void
var root: URL {
@ -101,7 +100,7 @@ class FuzzySearchService {
fetchReq.predicate = predicate
let chunkCount = Int(ceil(Double(count) / Double(coreDataBatchSize)))
for chunkIndex in (0..<chunkCount) {
for chunkIndex in 0..<chunkCount {
if self.shouldStop({ context.reset() }) { return }
let start = Swift.min(chunkIndex * coreDataBatchSize, count)
@ -123,7 +122,7 @@ class FuzzySearchService {
private func scanScoreFilesNeedScanning(
matcherPool: FuzzyMatcherPool,
context: NSManagedObjectContext,
callback: ([ScoredUrl]) -> ()
callback: ([ScoredUrl]) -> Void
) {
let req = self.fileFetchRequest("needsScanChildren == TRUE AND direntType == %d", [DT_DIR])
do {
@ -147,7 +146,7 @@ class FuzzySearchService {
matcherPool: FuzzyMatcherPool,
folderId: NSManagedObjectID,
context: NSManagedObjectContext,
callback: ([ScoredUrl]) -> ()
callback: ([ScoredUrl]) -> Void
) {
var saveCounter = 1
var counter = 1
@ -180,7 +179,9 @@ class FuzzySearchService {
let childFiles = childUrls
.filter { !$0.isPackage }
.map { url -> FileItem in self.file(fromUrl: url, pathStart: baton.pathStart, in: context) }
.map { url -> FileItem in
self.file(fromUrl: url, pathStart: baton.pathStart, in: context)
}
saveCounter += childFiles.count
counter += childFiles.count
@ -209,9 +210,9 @@ class FuzzySearchService {
// We have to re-fetch the Files in stack to get the parent-children relationship right.
// Since objectID survives NSManagedObjectContext.reset(), we can re-populate (re-fetch)
// stack using the objectIDs.
let ids = stack.map { $0.1.objectID }
let ids = stack.map(\.1.objectID)
stack = Array(zip(
stack.map { $0.0 },
stack.map(\.0),
ids.map { context.object(with: $0) as! FileItem }
))
}
@ -249,7 +250,7 @@ class FuzzySearchService {
private func scoreAllRegisteredFiles(
matcherPool: FuzzyMatcherPool,
context: NSManagedObjectContext,
callback: ([ScoredUrl]) -> ()
callback: ([ScoredUrl]) -> Void
) {
let files = context.registeredObjects
.compactMap { $0 as? FileItem }
@ -338,7 +339,7 @@ class FuzzySearchService {
} catch {
self.log.error(
"Could not fetch File with url \(folderUrl) "
+ "or could not save after setting needsScanChildren: \(error)"
+ "or could not save after setting needsScanChildren: \(error)"
)
}
@ -417,7 +418,7 @@ class FuzzySearchService {
}
func debug() {
let req = self.fileFetchRequest("needsScanChildren == TRUE AND direntType == %d", [DT_DIR]);
let req = self.fileFetchRequest("needsScanChildren == TRUE AND direntType == %d", [DT_DIR])
self.queue.async {
let moc = self.writeContext

View File

@ -8,11 +8,9 @@ import PureLayout
import RxSwift
class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
typealias StateType = AppState
enum Action {
case setOpenOnLaunch(Bool)
case setAfterLastWindowAction(AppState.AfterLastWindowAction)
case setOpenOnReactivation(Bool)
@ -20,11 +18,11 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
}
override var displayName: String {
return "General"
"General"
}
override var pinToContainer: Bool {
return true
true
}
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
@ -39,7 +37,8 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
self.defaultUsesVcsIgnoresCheckbox.boolState = state.openQuickly.defaultUsesVcsIgnores
self.lastWindowAction = state.afterLastWindowAction
self.afterLastWindowPopup.selectItem(at: indexToAfterLastWindowAction.firstIndex(of: state.afterLastWindowAction) ?? 0)
self.afterLastWindowPopup
.selectItem(at: indexToAfterLastWindowAction.firstIndex(of: state.afterLastWindowAction) ?? 0)
source
.observeOn(MainScheduler.instance)
@ -73,7 +72,8 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
private let afterLastWindowPopup = NSPopUpButton(forAutoLayout: ())
required init?(coder: NSCoder) {
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -81,15 +81,21 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
let paneTitle = self.paneTitleTextField(title: "General")
let openUntitledWindowTitle = self.titleTextField(title: "Open Untitled Window:")
self.configureCheckbox(button: self.openWhenLaunchingCheckbox,
title: "On launch",
action: #selector(GeneralPref.openUntitledWindowWhenLaunchingAction))
self.configureCheckbox(button: self.openOnReactivationCheckbox,
title: "On re-activation",
action: #selector(GeneralPref.openUntitledWindowOnReactivationAction))
self.configureCheckbox(button: self.defaultUsesVcsIgnoresCheckbox,
title: "Use VCS Ignores",
action: #selector(GeneralPref.defaultUsesVcsIgnoresAction))
self.configureCheckbox(
button: self.openWhenLaunchingCheckbox,
title: "On launch",
action: #selector(GeneralPref.openUntitledWindowWhenLaunchingAction)
)
self.configureCheckbox(
button: self.openOnReactivationCheckbox,
title: "On re-activation",
action: #selector(GeneralPref.openUntitledWindowOnReactivationAction)
)
self.configureCheckbox(
button: self.defaultUsesVcsIgnoresCheckbox,
title: "Use VCS Ignores",
action: #selector(GeneralPref.defaultUsesVcsIgnoresAction)
)
let whenLaunching = self.openWhenLaunchingCheckbox
let onReactivation = self.openOnReactivationCheckbox
@ -107,12 +113,12 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
let ignoreListTitle = self.titleTextField(title: "Open Quickly:")
let ignoreInfo =
self.infoTextField(markdown: #"""
When checked, the ignore files of VCSs, e.g. `gitignore`, will we used to ignore files.\
This checkbox will set the initial value for each VimR window.\
You can change this setting for each VimR window in the Open Quickly window.\
The behavior should be almost identical to that of
[The Silver Searcher](https://github.com/ggreer/the_silver_searcher).
"""#)
When checked, the ignore files of VCSs, e.g. `gitignore`, will we used to ignore files.\
This checkbox will set the initial value for each VimR window.\
You can change this setting for each VimR window in the Open Quickly window.\
The behavior should be almost identical to that of
[The Silver Searcher](https://github.com/ggreer/the_silver_searcher).
"""#)
let cliToolTitle = self.titleTextField(title: "CLI Tool:")
let cliToolButton = NSButton(forAutoLayout: ())
@ -150,7 +156,11 @@ The behavior should be almost identical to that of
openUntitledWindowTitle.autoAlignAxis(.baseline, toSameAxisOf: whenLaunching, withOffset: 0)
openUntitledWindowTitle.autoPinEdge(.right, to: .right, of: afterLastWindowTitle)
openUntitledWindowTitle.autoPinEdge(toSuperviewEdge: .left, withInset: 18, relation: .greaterThanOrEqual)
openUntitledWindowTitle.autoPinEdge(
toSuperviewEdge: .left,
withInset: 18,
relation: .greaterThanOrEqual
)
whenLaunching.autoPinEdge(.top, to: .bottom, of: paneTitle, withOffset: 18)
whenLaunching.autoPinEdge(.left, to: .right, of: openUntitledWindowTitle, withOffset: 5)
@ -158,7 +168,11 @@ The behavior should be almost identical to that of
onReactivation.autoPinEdge(.top, to: .bottom, of: whenLaunching, withOffset: 5)
onReactivation.autoPinEdge(.left, to: .left, of: whenLaunching)
onReactivation.autoPinEdge(toSuperviewEdge: .right, withInset: 18, relation: .greaterThanOrEqual)
onReactivation.autoPinEdge(
toSuperviewEdge: .right,
withInset: 18,
relation: .greaterThanOrEqual
)
afterLastWindowTitle.autoAlignAxis(.baseline, toSameAxisOf: lastWindow)
afterLastWindowTitle.autoPinEdge(toSuperviewEdge: .left, withInset: 18)
@ -168,7 +182,11 @@ The behavior should be almost identical to that of
ignoreListTitle.autoAlignAxis(.baseline, toSameAxisOf: vcsIg)
ignoreListTitle.autoPinEdge(.right, to: .right, of: openUntitledWindowTitle)
ignoreListTitle.autoPinEdge(toSuperviewEdge: .left, withInset: 18, relation: .greaterThanOrEqual)
ignoreListTitle.autoPinEdge(
toSuperviewEdge: .left,
withInset: 18,
relation: .greaterThanOrEqual
)
vcsIg.autoPinEdge(.top, to: .bottom, of: lastWindow, withOffset: 18)
vcsIg.autoPinEdge(.left, to: .right, of: ignoreListTitle, withOffset: 5)
@ -192,9 +210,9 @@ The behavior should be almost identical to that of
}
// MARK: - Actions
extension GeneralPref {
@objc func copyCliTool(_ sender: NSButton) {
extension GeneralPref {
@objc func copyCliTool(_: NSButton) {
let panel = NSOpenPanel()
panel.canChooseFiles = false
panel.canChooseDirectories = true
@ -205,14 +223,18 @@ extension GeneralPref {
}
guard let vimrUrl = Bundle.main.url(forResource: "vimr", withExtension: nil) else {
self.alert(title: "Something Went Wrong.",
info: "The CLI tool 'vimr' could not be found. Please re-download VimR and try again.")
self.alert(
title: "Something Went Wrong.",
info: "The CLI tool 'vimr' could not be found. Please re-download VimR and try again."
)
return
}
guard let targetUrl = panel.url?.appendingPathComponent("vimr") else {
self.alert(title: "Something Went Wrong.",
info: "The target directory could not be determined. Please try again with a different directory.")
self.alert(
title: "Something Went Wrong.",
info: "The target directory could not be determined. Please try again with a different directory."
)
return
}
@ -228,18 +250,18 @@ extension GeneralPref {
self.emit(.setDefaultUsesVcsIgnores(sender.boolState))
}
@objc func openUntitledWindowWhenLaunchingAction(_ sender: NSButton) {
@objc func openUntitledWindowWhenLaunchingAction(_: NSButton) {
self.emit(.setOpenOnLaunch(self.openWhenLaunchingCheckbox.boolState))
}
@objc func openUntitledWindowOnReactivationAction(_ sender: NSButton) {
@objc func openUntitledWindowOnReactivationAction(_: NSButton) {
self.emit(.setOpenOnReactivation(self.openOnReactivationCheckbox.boolState))
}
@objc func afterLastWindowAction(_ sender: NSPopUpButton) {
let index = sender.indexOfSelectedItem
guard index >= 0 && index <= 2 else {
guard index >= 0, index <= 2 else {
return
}
@ -256,4 +278,5 @@ extension GeneralPref {
}
}
private let indexToAfterLastWindowAction: [AppState.AfterLastWindowAction] = [.doNothing, .hide, .quit]
private let indexToAfterLastWindowAction: [AppState.AfterLastWindowAction] = [.doNothing, .hide,
.quit]

View File

@ -6,7 +6,6 @@
import Foundation
class GeneralPrefReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = GeneralPref.Action
@ -14,7 +13,6 @@ class GeneralPrefReducer: ReducerType {
var state = pair.state
switch pair.action {
case let .setOpenOnLaunch(value):
state.openNewMainWindowOnLaunch = value
@ -26,7 +24,6 @@ class GeneralPrefReducer: ReducerType {
case let .setDefaultUsesVcsIgnores(value):
state.openQuickly.defaultUsesVcsIgnores = value
}
return (state, pair.action, true)

View File

@ -3,11 +3,10 @@
* See LICENSE
*/
import Foundation
import Commons
import Foundation
class HtmlPreviewMiddleware: MiddlewareType {
static func selectFirstHtmlUrl(uuid: UUID) -> URL {
FileUtils.tempDir().appendingPathComponent("\(uuid)-select-first.html")
}

View File

@ -4,21 +4,19 @@
*/
import Cocoa
import RxSwift
import PureLayout
import WebKit
import EonilFSEvents
import MaterialIcons
import os
import PureLayout
import RxSwift
import WebKit
import Workspace
private let fileSystemEventsLatency = 1.0
private let monitorDispatchQueue = DispatchQueue.global(qos: .userInitiated)
class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
enum Action {
case selectHtmlFile(URL)
}
@ -70,9 +68,10 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
sinceWhen: EonilFSEventsEventID.getCurrentEventId(),
latency: fileSystemEventsLatency,
flags: [.fileEvents],
handler: { [weak self] event in
handler: { [weak self] _ in
self?.reloadWebview(with: serverUrl.payload)
})
}
)
self.monitor?.setDispatchQueue(monitorDispatchQueue)
try self.monitor?.start()
} catch {
@ -92,7 +91,7 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
private func reloadWebview(with url: URL) {
DispatchQueue.main.async {
self.webview.evaluateJavaScript("document.body.scrollTop") { (result, error) in
self.webview.evaluateJavaScript("document.body.scrollTop") { result, _ in
self.scrollTop = result as? Int ?? 0
}
}
@ -117,12 +116,15 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
private var monitor: EonilFSEventStream?
private let disposeBag = DisposeBag()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui
)
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
@objc func selectHtmlFile(sender: Any?) {
@objc func selectHtmlFile(sender _: Any?) {
let panel = NSOpenPanel()
panel.canChooseDirectories = false
panel.allowsMultipleSelection = false
@ -136,15 +138,13 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
func webView(_: WKWebView, didFinish _: WKNavigation!) {
self.webview.evaluateJavaScript("document.body.scrollTop = \(self.scrollTop)")
}
}
extension HtmlPreviewTool {
class InnerCustomToolbar: CustomToolBar {
fileprivate weak var htmlPreviewTool: HtmlPreviewTool? {
didSet { self.selectHtmlFile.target = self.htmlPreviewTool }
}
@ -182,6 +182,7 @@ extension HtmlPreviewTool {
selectHtmlFile.autoPinEdge(toSuperviewEdge: .right, withInset: InnerToolBar.itemPadding)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
}

View File

@ -6,11 +6,10 @@
import Foundation
class HtmlPreviewReducer {
static let basePath = "tools/html-preview"
static func serverUrl(baseUrl: URL, uuid: UUID) -> URL {
baseUrl.appendingPathComponent("\(uuid)/\(basePath)/index.html")
baseUrl.appendingPathComponent("\(uuid)/\(self.basePath)/index.html")
}
let mainWindow: MainWindowReducer
@ -22,7 +21,6 @@ class HtmlPreviewReducer {
}
class MainWindowReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
@ -32,7 +30,6 @@ class HtmlPreviewReducer {
var state = pair.state
switch pair.action.payload {
case .setTheme:
guard state.htmlPreview.htmlFile == nil else { return pair }
state.htmlPreview.server = Marked(
@ -41,7 +38,6 @@ class HtmlPreviewReducer {
default:
return pair
}
return (state, pair.action, true)
@ -51,7 +47,6 @@ class HtmlPreviewReducer {
}
class HtmlPreviewToolReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<HtmlPreviewTool.Action>
@ -60,13 +55,11 @@ class HtmlPreviewReducer {
func typedReduce(_ pair: ReduceTuple) -> ReduceTuple {
var state = pair.state
switch pair.action.payload {
case .selectHtmlFile(let url):
case let .selectHtmlFile(url):
state.htmlPreview.htmlFile = url
state.htmlPreview.server = Marked(
HtmlPreviewReducer.serverUrl(baseUrl: self.baseServerUrl, uuid: state.uuid)
)
}
return (state, pair.action, true)

View File

@ -4,11 +4,10 @@
*/
import Foundation
import Swifter
import os
import Swifter
class HttpServerMiddleware {
let htmlPreviewTool: HtmlPreviewToolMiddleware
let htmlPreviewMainWindow: HtmlPreviewMainWindowMiddleware
let markdownPreview: MarkdownPreviewMiddleware
@ -63,15 +62,18 @@ class HttpServerMiddleware {
}
}
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware
)
class HtmlPreviewMainWindowMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
fileprivate init(server: HttpServer, baseUrl: URL, cssUrl: URL, htmlTemplates: HtmlTemplates) {
fileprivate init(server: HttpServer, baseUrl: URL, cssUrl: URL,
htmlTemplates _: HtmlTemplates)
{
self.server = server
self.baseUrl = baseUrl
self.cssUrl = cssUrl
@ -108,18 +110,21 @@ class HttpServerMiddleware {
private let baseUrl: URL
private let cssUrl: URL
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware
)
private func fullUrl(with path: String) -> URL { self.baseUrl.appendingPathComponent(path) }
}
class HtmlPreviewToolMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<HtmlPreviewTool.Action>
fileprivate init(server: HttpServer, baseUrl: URL, cssUrl: URL, htmlTemplates: HtmlTemplates) {
fileprivate init(server: HttpServer, baseUrl: URL, cssUrl: URL,
htmlTemplates _: HtmlTemplates)
{
self.server = server
self.baseUrl = baseUrl
self.cssUrl = cssUrl
@ -152,14 +157,15 @@ class HttpServerMiddleware {
private let baseUrl: URL
private let cssUrl: URL
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware
)
private func fullUrl(with path: String) -> URL { self.baseUrl.appendingPathComponent(path) }
}
class MarkdownPreviewMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
@ -213,8 +219,10 @@ class HttpServerMiddleware {
private let cssUrl: URL
private let baseCssUrl: URL
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware
)
private func fullUrl(with path: String) -> URL { self.baseUrl.appendingPathComponent(path) }
}

View File

@ -7,11 +7,11 @@ import Cocoa
import PureLayout
class ImageAndTextTableCell: NSTableCellView {
private let _textField = NSTextField(forAutoLayout: ())
private let _imageView = NSImageView(forAutoLayout: ())
// MARK: - API
static let font = NSFont.systemFont(ofSize: 12)
static let widthWithoutText = (2 + 16 + 4 + 2).cgf
@ -86,5 +86,6 @@ class ImageAndTextTableCell: NSTableCellView {
return self
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
}

View File

@ -8,21 +8,19 @@ import PureLayout
import RxSwift
class KeysPref: PrefPane, UiComponent, NSTextFieldDelegate {
typealias StateType = AppState
enum Action {
case isLeftOptionMeta(Bool)
case isRightOptionMeta(Bool)
}
override var displayName: String {
return "Keys"
"Keys"
}
override var pinToContainer: Bool {
return true
true
}
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
@ -40,7 +38,7 @@ class KeysPref: PrefPane, UiComponent, NSTextFieldDelegate {
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
if self.isLeftOptionMeta != state.mainWindowTemplate.isLeftOptionMeta
|| self.isRightOptionMeta != state.mainWindowTemplate.isRightOptionMeta
|| self.isRightOptionMeta != state.mainWindowTemplate.isRightOptionMeta
{
self.isLeftOptionMeta = state.mainWindowTemplate.isLeftOptionMeta
self.isRightOptionMeta = state.mainWindowTemplate.isRightOptionMeta
@ -60,7 +58,8 @@ class KeysPref: PrefPane, UiComponent, NSTextFieldDelegate {
private let isLeftOptionMetaCheckbox = NSButton(forAutoLayout: ())
private let isRightOptionMetaCheckbox = NSButton(forAutoLayout: ())
required init?(coder: NSCoder) {
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -73,14 +72,18 @@ class KeysPref: PrefPane, UiComponent, NSTextFieldDelegate {
let paneTitle = self.paneTitleTextField(title: "Keys")
let isLeftOptionMeta = self.isLeftOptionMetaCheckbox
self.configureCheckbox(button: isLeftOptionMeta,
title: "Use Left Option as Meta",
action: #selector(KeysPref.isLeftOptionMetaAction(_:)))
self.configureCheckbox(
button: isLeftOptionMeta,
title: "Use Left Option as Meta",
action: #selector(KeysPref.isLeftOptionMetaAction(_:))
)
let isRightOptionMeta = self.isRightOptionMetaCheckbox
self.configureCheckbox(button: isRightOptionMeta,
title: "Use Right Option as Meta",
action: #selector(KeysPref.isRightOptionMetaAction(_:)))
self.configureCheckbox(
button: isRightOptionMeta,
title: "Use Right Option as Meta",
action: #selector(KeysPref.isRightOptionMetaAction(_:))
)
let metaInfo = self.infoTextField(markdown: #"""
When an Option key is set to Meta, then every input containing the corresponding Option key will\
@ -111,8 +114,8 @@ class KeysPref: PrefPane, UiComponent, NSTextFieldDelegate {
}
// MARK: - Actions
extension KeysPref {
extension KeysPref {
@objc func isLeftOptionMetaAction(_ sender: NSButton) {
self.emit(.isLeftOptionMeta(sender.boolState))
}

View File

@ -6,7 +6,6 @@
import Foundation
class KeysPrefReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = KeysPref.Action
@ -14,15 +13,13 @@ class KeysPrefReducer: ReducerType {
var state = pair.state
switch pair.action {
case let .isLeftOptionMeta(value):
state.mainWindowTemplate.isLeftOptionMeta = value
state.mainWindows.keys.forEach { state.mainWindows[$0]?.isLeftOptionMeta = value }
state.mainWindows.keys.forEach { state.mainWindows[$0]?.isLeftOptionMeta = value }
case let .isRightOptionMeta(value):
state.mainWindowTemplate.isRightOptionMeta = value
state.mainWindows.keys.forEach { state.mainWindows[$0]?.isRightOptionMeta = value }
state.mainWindows.keys.forEach { state.mainWindows[$0]?.isRightOptionMeta = value }
}
return (state, pair.action, true)

View File

@ -4,20 +4,20 @@
*/
import Cocoa
import RxSwift
import MessagePack
import Commons
import MessagePack
import RxSwift
import Workspace
// MARK: - RpcEvent Actions
extension MainWindow {
extension MainWindow {
func rpcEventAction(params rawParams: [MessagePackValue]) {
guard rawParams.count > 0 else { return }
guard let strEvent = rawParams[0].stringValue,
let event = RpcEvent(rawValue: "\(RpcEvent.prefix).\(strEvent)")
else {
else {
return
}
let params = Array(rawParams.suffix(from: 1))
@ -64,7 +64,7 @@ extension MainWindow {
guard let fontName = params[0].stringValue,
let fontSize = params[1].int64Value,
let font = NSFont(name: fontName, size: fontSize.cgf)
else {
else {
return
}
@ -79,9 +79,8 @@ extension MainWindow {
case .setCharacterspacing:
guard params.count == 1 else { return }
guard let characterspacing = params[0].floatValue else { return }
self.emit(self.uuidAction(for: .setCharacterspacing(characterspacing.cgf)))
self.emit(self.uuidAction(for: .setCharacterspacing(characterspacing.cgf)))
}
}
@ -119,16 +118,16 @@ extension MainWindow {
}
// MARK: - File Menu Item Actions
extension MainWindow {
@IBAction func newTab(_ sender: Any?) {
extension MainWindow {
@IBAction func newTab(_: Any?) {
self.neoVimView
.newTab()
.subscribe()
.disposed(by: self.disposeBag)
}
@IBAction func openDocument(_ sender: Any?) {
@IBAction func openDocument(_: Any?) {
let panel = NSOpenPanel()
panel.canChooseDirectories = true
panel.allowsMultipleSelection = true
@ -155,16 +154,16 @@ extension MainWindow {
}
}
@IBAction func openQuickly(_ sender: Any?) {
@IBAction func openQuickly(_: Any?) {
self.emit(self.uuidAction(for: .openQuickly))
}
@IBAction func closeWindow(_ sender: Any?) {
@IBAction func closeWindow(_: Any?) {
self.closeWindow = true
self.window.performClose(nil)
}
@IBAction func saveDocument(_ sender: Any?) {
@IBAction func saveDocument(_: Any?) {
self.neoVimView
.currentBuffer()
.observeOn(MainScheduler.instance)
@ -185,7 +184,7 @@ extension MainWindow {
.disposed(by: self.disposeBag)
}
@IBAction func saveDocumentAs(_ sender: Any?) {
@IBAction func saveDocumentAs(_: Any?) {
self.neoVimView
.currentBuffer()
.observeOn(MainScheduler.instance)
@ -194,7 +193,8 @@ extension MainWindow {
self.neoVimView
.saveCurrentTab(url: url)
.andThen(
curBuf.isDirty ? self.neoVimView.openInNewTab(urls: [url]) : self.neoVimView.openInCurrentTab(url: url)
curBuf.isDirty ? self.neoVimView.openInNewTab(urls: [url]) : self.neoVimView
.openInCurrentTab(url: url)
)
.subscribe()
.disposed(by: self.disposeBag)
@ -214,7 +214,9 @@ extension MainWindow {
let alert = NSAlert()
alert.addButton(withTitle: "OK")
alert.messageText = "Invalid File Name"
alert.informativeText = "The file name you have entered cannot be used. Please use a different name."
alert
.informativeText =
"The file name you have entered cannot be used. Please use a different name."
alert.alertStyle = .warning
alert.runModal()
@ -231,36 +233,36 @@ extension MainWindow {
}
// MARK: - Tools Menu Item Actions
extension MainWindow {
@IBAction func toggleAllTools(_ sender: Any?) {
extension MainWindow {
@IBAction func toggleAllTools(_: Any?) {
self.workspace.toggleAllTools()
self.focusNvimView(self)
self.emit(self.uuidAction(for: .toggleAllTools(self.workspace.isAllToolsVisible)))
}
@IBAction func toggleToolButtons(_ sender: Any?) {
@IBAction func toggleToolButtons(_: Any?) {
self.workspace.toggleToolButtons()
self.emit(self.uuidAction(for: .toggleToolButtons(self.workspace.isToolButtonsVisible)))
}
@IBAction func toggleFileBrowser(_ sender: Any?) {
@IBAction func toggleFileBrowser(_: Any?) {
guard let fileBrowser = self.fileBrowserContainer else { return }
self.toggle(tool: fileBrowser, toolType: .fileBrowser)
}
@IBAction func toggleBufferList(_ sender: Any?) {
@IBAction func toggleBufferList(_: Any?) {
guard let bufferList = self.buffersListContainer else { return }
self.toggle(tool: bufferList, toolType: .bufferList)
}
@IBAction func toggleMarkdownPreview(_ sender: Any?) {
@IBAction func toggleMarkdownPreview(_: Any?) {
guard let markdownPreview = self.previewContainer else { return }
self.toggle(tool: markdownPreview, toolType: .markdownPreview)
}
@IBAction func toggleHtmlPreview(_ sender: Any?) {
@IBAction func toggleHtmlPreview(_: Any?) {
guard let htmlPreview = self.htmlPreviewContainer else { return }
self.toggle(tool: htmlPreview, toolType: .htmlPreview)
}
@ -287,8 +289,8 @@ extension MainWindow {
}
// MARK: - NSUserInterfaceValidationsProtocol
extension MainWindow {
extension MainWindow {
func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
let canSave = self.neoVimView.currentBuffer().syncValue()?.type == ""
let canSaveAs = canSave
@ -303,31 +305,29 @@ extension MainWindow {
}
switch action {
case #selector(toggleAllTools(_:)), #selector(toggleToolButtons(_:)):
case #selector(self.toggleAllTools(_:)), #selector(self.toggleToolButtons(_:)):
return canToggleTools
case #selector(toggleFileBrowser(_:)):
case #selector(self.toggleFileBrowser(_:)):
return canToggleFileBrowser
case #selector(focusNvimView(_:)):
case #selector(self.focusNvimView(_:)):
return canFocusNvimView
case #selector(openDocument(_:)):
case #selector(self.openDocument(_:)):
return canOpen
case #selector(openQuickly(_:)):
case #selector(self.openQuickly(_:)):
return canOpenQuickly
case #selector(saveDocument(_:)):
case #selector(self.saveDocument(_:)):
return canSave
case #selector(saveDocumentAs(_:)):
case #selector(self.saveDocumentAs(_:)):
return canSaveAs
default:
return true
}
}
}

View File

@ -7,9 +7,9 @@ import Cocoa
import PureLayout
// MARK: - Custom title
extension MainWindow {
func themeTitlebar(grow: Bool) {
extension MainWindow {
func themeTitlebar(grow _: Bool) {
if self.window.styleMask.contains(.fullScreen) {
return
}
@ -100,7 +100,8 @@ extension MainWindow {
self.titleView = title
if let button = self.window.standardWindowButton(.documentIconButton) {
button.removeFromSuperview() // remove the rep icon from the original superview and add it to content view
button
.removeFromSuperview() // remove the rep icon from the original superview and add it to content view
contentView.addSubview(button)
button.autoSetDimension(.width, toSize: 16)
button.autoSetDimension(.height, toSize: 16)
@ -110,11 +111,15 @@ extension MainWindow {
// rightView.left = leftView.right + gap
// rightView.right = parentView.centerX + (leftView.width + gap + rightView.width) / 2 - 4
// The (-4) at the end is an empirical value...
contentView.addConstraint(NSLayoutConstraint(item: title, attribute: .left,
relatedBy: .equal,
toItem: button, attribute: .right,
multiplier: 1,
constant: repIconToTitleGap))
contentView.addConstraint(NSLayoutConstraint(
item: title,
attribute: .left,
relatedBy: .equal,
toItem: button,
attribute: .right,
multiplier: 1,
constant: repIconToTitleGap
))
contentView.addConstraint(
// Here we use title.intrinsicContentSize instead of title.frame because title.frame is still zero.
NSLayoutConstraint(
@ -122,7 +127,8 @@ extension MainWindow {
relatedBy: .equal,
toItem: contentView, attribute: .centerX,
multiplier: 1,
constant: -4 + (button.frame.width + repIconToTitleGap + title.intrinsicContentSize.width) / 2
constant: -4 +
(button.frame.width + repIconToTitleGap + title.intrinsicContentSize.width) / 2
)
)
@ -149,4 +155,4 @@ extension MainWindow {
}
}
private let repIconToTitleGap = (4.0).cgf
private let repIconToTitleGap = 4.0.cgf

View File

@ -4,14 +4,14 @@
*/
import Cocoa
import RxSwift
import NvimView
import RxPack
import RxSwift
import Workspace
// MARK: - NvimViewDelegate
extension MainWindow {
extension MainWindow {
// Use only when Cmd-Q'ing
func waitTillNvimExits() {
self.neoVimView.waitTillNvimExits()
@ -35,7 +35,9 @@ extension MainWindow {
self.window.toggleFullScreen(nil)
}
guard let cliPipePath = self.cliPipePath, FileManager.default.fileExists(atPath: cliPipePath) else {
guard let cliPipePath = self.cliPipePath,
FileManager.default.fileExists(atPath: cliPipePath)
else {
return
}
@ -92,8 +94,10 @@ extension MainWindow {
self
.updateCssColors()
.subscribe(onSuccess: { colors in
self.emit(self.uuidAction(
for: .setTheme(Theme(from: nvimTheme, additionalColorDict: colors)))
self.emit(
self.uuidAction(
for: .setTheme(Theme(from: nvimTheme, additionalColorDict: colors))
)
)
})
.disposed(by: self.disposeBag)
@ -103,10 +107,12 @@ extension MainWindow {
let alert = NSAlert()
alert.addButton(withTitle: "Close")
alert.messageText = "Sorry, an error occurred."
alert.informativeText = "VimR encountered an error from which it cannot recover. This window will now close.\n"
+ reason
alert
.informativeText =
"VimR encountered an error from which it cannot recover. This window will now close.\n"
+ reason
alert.alertStyle = .critical
alert.beginSheetModal(for: self.window) { response in
alert.beginSheetModal(for: self.window) { _ in
self.windowController.close()
}
}
@ -132,7 +138,7 @@ extension MainWindow {
"CursorColumn", // code background and foreground
]
typealias HlResult = Dictionary<String, RxNeovimApi.Value>
typealias HlResult = [String: RxNeovimApi.Value]
typealias ColorNameHlResultTuple = (colorName: String, hlResult: HlResult)
typealias ColorNameObservableTuple = (colorName: String, observable: Observable<HlResult>)
@ -164,7 +170,6 @@ extension MainWindow {
// MARK: - NSWindowDelegate
extension MainWindow {
func windowWillEnterFullScreen(_: Notification) {
self.unthemeTitlebar(dueFullScreen: true)
}
@ -175,20 +180,24 @@ extension MainWindow {
}
}
func windowDidBecomeMain(_ notification: Notification) {
self.emit(self.uuidAction(for: .becomeKey(isFullScreen: self.window.styleMask.contains(.fullScreen))))
func windowDidBecomeMain(_: Notification) {
self
.emit(
self
.uuidAction(for: .becomeKey(isFullScreen: self.window.styleMask.contains(.fullScreen)))
)
self.neoVimView.didBecomeMain().subscribe().disposed(by: self.disposeBag)
}
func windowDidResignMain(_ notification: Notification) {
func windowDidResignMain(_: Notification) {
self.neoVimView.didResignMain().subscribe().disposed(by: self.disposeBag)
}
func windowDidMove(_ notification: Notification) {
func windowDidMove(_: Notification) {
self.emit(self.uuidAction(for: .frameChanged(to: self.window.frame)))
}
func windowDidResize(_ notification: Notification) {
func windowDidResize(_: Notification) {
if self.window.styleMask.contains(.fullScreen) {
return
}
@ -199,7 +208,7 @@ extension MainWindow {
func windowShouldClose(_: NSWindow) -> Bool {
defer { self.closeWindow = false }
if (self.neoVimView.isBlocked().syncValue() ?? false) {
if self.neoVimView.isBlocked().syncValue() ?? false {
let alert = NSAlert()
alert.messageText = "Nvim is waiting for your input."
alert.alertStyle = .informational
@ -221,7 +230,7 @@ extension MainWindow {
return false
}
guard (self.neoVimView.isCurrentBufferDirty().syncValue() ?? false) else {
guard self.neoVimView.isCurrentBufferDirty().syncValue() ?? false else {
try? self.neoVimView.closeCurrentTab().wait()
return false
}
@ -249,13 +258,13 @@ extension MainWindow {
}
// MARK: - WorkspaceDelegate
extension MainWindow {
func resizeWillStart(workspace: Workspace, tool: WorkspaceTool?) {
extension MainWindow {
func resizeWillStart(workspace _: Workspace, tool _: WorkspaceTool?) {
self.neoVimView.enterResizeMode()
}
func resizeDidEnd(workspace: Workspace, tool: WorkspaceTool?) {
func resizeDidEnd(workspace _: Workspace, tool: WorkspaceTool?) {
self.neoVimView.exitResizeMode()
if let workspaceTool = tool, let toolIdentifier = self.toolIdentifier(for: workspaceTool) {
@ -270,13 +279,14 @@ extension MainWindow {
}
func moved(tool: WorkspaceTool) {
let tools = self.workspace.orderedTools.compactMap { (tool: WorkspaceTool) -> (Tools, WorkspaceTool)? in
guard let toolId = self.toolIdentifier(for: tool) else {
return nil
}
let tools = self.workspace.orderedTools
.compactMap { (tool: WorkspaceTool) -> (Tools, WorkspaceTool)? in
guard let toolId = self.toolIdentifier(for: tool) else {
return nil
}
return (toolId, tool)
}
return (toolId, tool)
}
self.emit(self.uuidAction(for: .setToolsState(tools)))
}

View File

@ -8,9 +8,7 @@ import NvimView
import Workspace
extension MainWindow {
enum Action {
case cd(to: URL)
case setBufferList([NvimView.Buffer])
@ -46,7 +44,6 @@ extension MainWindow {
}
enum FocusableView {
case neoVimView
case fileBrowser
case bufferList
@ -55,13 +52,12 @@ extension MainWindow {
}
enum Tools: String, Codable {
static let all = Set(
[
Tools.fileBrowser,
Tools.buffersList,
Tools.preview,
Tools.htmlPreview
Tools.htmlPreview,
]
)
@ -72,7 +68,6 @@ extension MainWindow {
}
enum OpenMode {
case `default`
case currentTab
case newTab

View File

@ -4,18 +4,18 @@
*/
import Cocoa
import RxSwift
import NvimView
import PureLayout
import os
import PureLayout
import RxSwift
import Workspace
class MainWindow: NSObject,
UiComponent,
NSWindowDelegate,
NSUserInterfaceValidations,
WorkspaceDelegate {
UiComponent,
NSWindowDelegate,
NSUserInterfaceValidations,
WorkspaceDelegate
{
typealias StateType = State
let disposeBag = DisposeBag()
@ -67,7 +67,8 @@ class MainWindow: NSObject,
var sourceFileUrls = [URL]()
if let sourceFileUrl = Bundle(for: MainWindow.self)
.url(forResource: "com.qvacua.VimR", withExtension: "vim") {
.url(forResource: "com.qvacua.VimR", withExtension: "vim")
{
sourceFileUrls.append(sourceFileUrl)
}
@ -97,9 +98,11 @@ class MainWindow: NSObject,
}
if state.activeTools[.htmlPreview] == true {
self.htmlPreview = HtmlPreviewTool(source: source,
emitter: emitter,
state: state)
self.htmlPreview = HtmlPreviewTool(
source: source,
emitter: emitter,
state: state
)
let htmlPreviewConfig = WorkspaceTool.Config(
title: "HTML",
view: self.htmlPreview!,
@ -107,7 +110,7 @@ class MainWindow: NSObject,
)
self.htmlPreviewContainer = WorkspaceTool(htmlPreviewConfig)
self.htmlPreviewContainer!.dimension = state.tools[.htmlPreview]?
.dimension ?? 250
.dimension ?? 250
tools[.htmlPreview] = self.htmlPreviewContainer
}
@ -123,8 +126,8 @@ class MainWindow: NSObject,
)
self.fileBrowserContainer = WorkspaceTool(fileBrowserConfig)
self.fileBrowserContainer!.dimension = state
.tools[.fileBrowser]?
.dimension ?? 200
.tools[.fileBrowser]?
.dimension ?? 200
tools[.fileBrowser] = self.fileBrowserContainer
}
@ -132,12 +135,14 @@ class MainWindow: NSObject,
self.buffersList = BuffersList(
source: source, emitter: emitter, state: state
)
let buffersListConfig = WorkspaceTool.Config(title: "Buffers",
view: self.buffersList!)
let buffersListConfig = WorkspaceTool.Config(
title: "Buffers",
view: self.buffersList!
)
self.buffersListContainer = WorkspaceTool(buffersListConfig)
self.buffersListContainer!.dimension = state
.tools[.buffersList]?
.dimension ?? 200
.tools[.buffersList]?
.dimension ?? 200
tools[.buffersList] = self.buffersListContainer
}
@ -163,11 +168,13 @@ class MainWindow: NSObject,
return
}
self.workspace.append(tool: tool,
location: state.tools[toolId]?.location ?? .left)
self.workspace.append(
tool: tool,
location: state.tools[toolId]?.location ?? .left
)
}
self.tools.forEach { (toolId, toolContainer) in
self.tools.forEach { toolId, toolContainer in
if state.tools[toolId]?.open == true {
toolContainer.toggle()
}
@ -204,7 +211,7 @@ class MainWindow: NSObject,
}
func uuidAction(for action: Action) -> UuidAction<Action> {
return UuidAction(uuid: self.uuid, action: action)
UuidAction(uuid: self.uuid, action: action)
}
func show() {
@ -213,7 +220,7 @@ class MainWindow: NSObject,
// The following should only be used when Cmd-Q'ing
func quitNeoVimWithoutSaving() -> Completable {
return self.neoVimView.quitNeoVimWithoutSaving()
self.neoVimView.quitNeoVimWithoutSaving()
}
@IBAction func debug2(_: Any?) {
@ -222,10 +229,11 @@ class MainWindow: NSObject,
theme.background = .yellow
theme.highlightForeground = .orange
theme.highlightBackground = .red
self.emit(uuidAction(for: .setTheme(theme)))
self.emit(self.uuidAction(for: .setTheme(theme)))
}
// MARK: - Private
private var currentBuffer: NvimView.Buffer?
private var goToLineFromCli: Marked<Int>?
@ -246,8 +254,10 @@ class MainWindow: NSObject,
private var usesTheme = true
private var lastThemeMark = Token()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui
)
private func setupScrollAndCursorDebouncers() {
Observable
@ -265,12 +275,11 @@ class MainWindow: NSObject,
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] event in
switch event {
case .neoVimStopped: self?.neoVimStopped()
case .setTitle(let title): self?.set(title: title)
case let .setTitle(title): self?.set(title: title)
case .setDirtyStatus(let dirty): self?.set(dirtyStatus: dirty)
case let .setDirtyStatus(dirty): self?.set(dirtyStatus: dirty)
case .cwdChanged: self?.cwdChanged()
@ -278,32 +287,30 @@ class MainWindow: NSObject,
case .tabChanged: self?.tabChanged()
case .newCurrentBuffer(let curBuf): self?.newCurrentBuffer(curBuf)
case let .newCurrentBuffer(curBuf): self?.newCurrentBuffer(curBuf)
case .bufferWritten(let buf): self?.bufferWritten(buf)
case let .bufferWritten(buf): self?.bufferWritten(buf)
case .colorschemeChanged(let theme): self?.colorschemeChanged(to: theme)
case let .colorschemeChanged(theme): self?.colorschemeChanged(to: theme)
case .ipcBecameInvalid(let reason):
case let .ipcBecameInvalid(reason):
self?.ipcBecameInvalid(reason: reason)
case .scroll: self?.scroll()
case .cursor(let position): self?.cursor(to: position)
case let .cursor(position): self?.cursor(to: position)
case .initVimError: self?.showInitError()
case .apiError(let error, let msg):
case let .apiError(error, msg):
self?.log.error("Got api error with msg '\(msg)' and error: \(error)")
case .rpcEvent(let params): self?.rpcEventAction(params: params)
case let .rpcEvent(params): self?.rpcEventAction(params: params)
case .rpcEventSubscribed: break
}
}, onError: { error in
// FIXME call onError
// FIXME: call onError
self.log.error(error)
})
.disposed(by: self.disposeBag)
@ -318,7 +325,8 @@ class MainWindow: NSObject,
}
if state.viewToBeFocused != nil,
case .neoVimView = state.viewToBeFocused! {
case .neoVimView = state.viewToBeFocused!
{
self.window.makeFirstResponder(self.neoVimView)
}
@ -331,11 +339,11 @@ class MainWindow: NSObject,
Completable
.empty()
.andThen {
if state.preview.status == .markdown
&& state.previewTool.isReverseSearchAutomatically
&& state.preview.previewPosition
.hasDifferentMark(as: self.previewPosition) {
if state.preview.status == .markdown,
state.previewTool.isReverseSearchAutomatically,
state.preview.previewPosition
.hasDifferentMark(as: self.previewPosition)
{
self.previewPosition = state.preview.previewPosition
return self.neoVimView.cursorGo(
to: state.preview.previewPosition.payload
@ -389,7 +397,8 @@ class MainWindow: NSObject,
self.unthemeTitlebar(dueFullScreen: false)
self.window.backgroundColor = .windowBackgroundColor
self.workspace.theme = .default
})
}
)
self.usesTheme = state.appearance.usesTheme
self.currentBuffer = state.currentBuffer
@ -404,7 +413,8 @@ class MainWindow: NSObject,
self.neoVimView.isRightOptionMeta = state.isRightOptionMeta
if self.neoVimView.trackpadScrollResistance
!= state.trackpadScrollResistance.cgf {
!= state.trackpadScrollResistance.cgf
{
self.neoVimView.trackpadScrollResistance = CGFloat(
state.trackpadScrollResistance
)
@ -420,9 +430,10 @@ class MainWindow: NSObject,
}
if self.defaultFont != state.appearance.font
|| self.linespacing != state.appearance.linespacing
|| self.characterspacing != state.appearance.characterspacing
|| self.usesLigatures != state.appearance.usesLigatures {
|| self.linespacing != state.appearance.linespacing
|| self.characterspacing != state.appearance.characterspacing
|| self.usesLigatures != state.appearance.usesLigatures
{
self.defaultFont = state.appearance.font
self.linespacing = state.appearance.linespacing
self.characterspacing = state.appearance.characterspacing
@ -506,10 +517,10 @@ class MainWindow: NSObject,
notification.identifier = UUID().uuidString
notification.title = "Error during initialization"
notification.informativeText =
"""
There was an error during the initialization of NeoVim.
Use :messages to view the error messages.
"""
"""
There was an error during the initialization of NeoVim.
Use :messages to view the error messages.
"""
NSUserNotificationCenter.default.deliver(notification)
}

View File

@ -6,7 +6,6 @@
import Foundation
class MainWindowReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
@ -14,11 +13,10 @@ class MainWindowReducer: ReducerType {
var state = tuple.state
switch tuple.action.payload {
case let .frameChanged(to:frame):
case let .frameChanged(to: frame):
state.frame = frame
case let .cd(to:cwd):
case let .cd(to: cwd):
if state.cwd != cwd {
state.cwd = cwd
}
@ -41,9 +39,11 @@ class MainWindowReducer: ReducerType {
state.viewToBeFocused = view
case let .setState(for: tool, with: workspaceTool):
state.tools[tool] = WorkspaceToolState(location: workspaceTool.location,
dimension: workspaceTool.dimension,
open: workspaceTool.isSelected)
state.tools[tool] = WorkspaceToolState(
location: workspaceTool.location,
dimension: workspaceTool.dimension,
open: workspaceTool.isSelected
)
if workspaceTool.isSelected {
state.tools
.filter { $0 != tool && $1.location == workspaceTool.location }
@ -56,9 +56,11 @@ class MainWindowReducer: ReducerType {
let toolId = toolPair.0
let tool = toolPair.1
state.tools[toolId] = WorkspaceToolState(location: tool.location,
dimension: tool.dimension,
open: tool.isSelected)
state.tools[toolId] = WorkspaceToolState(
location: tool.location,
dimension: tool.dimension,
open: tool.isSelected
)
if tool.isSelected {
state.tools
@ -83,7 +85,6 @@ class MainWindowReducer: ReducerType {
default:
return tuple
}
return (state, tuple.action, true)

View File

@ -3,12 +3,11 @@
* See LICENSE
*/
import Foundation
import Down
import Foundation
import os
class MarkdownPreviewMiddleware {
let markdownTool: MarkdownToolMiddleware
let mainWindow: MainWindowMiddleware
@ -19,7 +18,6 @@ class MarkdownPreviewMiddleware {
}
class PreviewGenerator {
init() {
// We know that the files are there!
self.template = try! String(contentsOf: Resources.markdownTemplateUrl)
@ -39,10 +37,9 @@ class MarkdownPreviewMiddleware {
}
self.removePreviewHtmlFile(uuid: uuid)
guard let htmlUrl = preview.html else {return }
guard let htmlUrl = preview.html else { return }
switch preview.status {
case .none:
self.writePage(html: self.emptyHtml, uuid: uuid, url: htmlUrl)
@ -63,7 +60,6 @@ class MarkdownPreviewMiddleware {
self.log.error("error while rendering \(buffer) to \(htmlUrl): \(error)")
return
}
}
}
@ -101,15 +97,17 @@ class MarkdownPreviewMiddleware {
private let template: String
private var previewFiles = [UUID: URL]()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware
)
private func render(_ bufferUrl: URL, to htmlUrl: URL) throws {
let md = try String(contentsOf: bufferUrl)
let down = Down(markdownString: md)
let body = try down.toHTML(DownOptions.sourcePos)
let html = filledTemplate(body: body, title: bufferUrl.lastPathComponent)
let html = self.filledTemplate(body: body, title: bufferUrl.lastPathComponent)
let htmlFilePath = htmlUrl.path
try html.write(toFile: htmlFilePath, atomically: true, encoding: .utf8)
@ -128,7 +126,6 @@ class MarkdownPreviewMiddleware {
}
class MarkdownToolMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MarkdownTool.Action>
@ -150,7 +147,6 @@ class MarkdownPreviewMiddleware {
}
class MainWindowMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
@ -162,14 +158,12 @@ class MarkdownPreviewMiddleware {
let uuidAction = tuple.action
switch uuidAction.payload {
case .newCurrentBuffer: fallthrough
case .bufferWritten: fallthrough
case .setTheme:
self.generator.apply(result.state, uuid: uuidAction.uuid)
default: return result
}
return result

View File

@ -4,12 +4,11 @@
*/
import Cocoa
import NvimView
import Commons
import NvimView
class MarkdownPreviewReducer {
static private func previewState(
private static func previewState(
for uuid: UUID,
baseUrl: URL,
buffer: NvimView.Buffer?,
@ -58,7 +57,6 @@ class MarkdownPreviewReducer {
}
class PreviewToolReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MarkdownTool.Action>
@ -66,7 +64,6 @@ class MarkdownPreviewReducer {
var state = tuple.state
switch tuple.action.payload {
case .refreshNow:
state.preview = MarkdownPreviewReducer.previewState(
for: tuple.state.uuid,
@ -77,20 +74,25 @@ class MarkdownPreviewReducer {
)
state.preview.lastSearch = .reload
case let .reverseSearch(to:position):
case let .reverseSearch(to: position):
state.preview.previewPosition = Marked(position)
state.preview.lastSearch = .reverse
case let .scroll(to:position):
case let .scroll(to: position):
if state.preview.lastSearch == .reload {
state.preview.lastSearch = .none
break;
break
}
guard state.previewTool.isReverseSearchAutomatically && state.preview.lastSearch != .forward else {
guard state.previewTool.isReverseSearchAutomatically,
state.preview.lastSearch != .forward
else {
state.preview.lastSearch = .none
state.preview.previewPosition = Marked(mark: state.preview.previewPosition.mark, payload: position)
break;
state.preview.previewPosition = Marked(
mark: state.preview.previewPosition.mark,
payload: position
)
break
}
state.preview.previewPosition = Marked(position)
@ -98,7 +100,6 @@ class MarkdownPreviewReducer {
default:
return tuple
}
return (state, tuple.action, true)
@ -110,7 +111,6 @@ class MarkdownPreviewReducer {
}
class BuffersListReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<BuffersList.Action>
@ -118,7 +118,6 @@ class MarkdownPreviewReducer {
var state = tuple.state
switch tuple.action.payload {
case let .open(buffer):
state.preview = MarkdownPreviewReducer.previewState(
for: tuple.state.uuid,
@ -128,7 +127,6 @@ class MarkdownPreviewReducer {
previewPosition: Marked(.beginning)
)
state.preview.lastSearch = .none
}
return (state, tuple.action, true)
@ -140,7 +138,6 @@ class MarkdownPreviewReducer {
}
class MainWindowReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
@ -148,7 +145,6 @@ class MarkdownPreviewReducer {
var state = tuple.state
switch tuple.action.payload {
case let .newCurrentBuffer(buffer):
state.preview = MarkdownPreviewReducer.previewState(
for: tuple.state.uuid,
@ -169,14 +165,15 @@ class MarkdownPreviewReducer {
)
state.preview.lastSearch = .reload
case let .setCursor(to:position):
case let .setCursor(to: position):
if state.preview.lastSearch == .reload {
state.preview.lastSearch = .none
break
}
guard state.previewTool.isForwardSearchAutomatically,
state.preview.lastSearch != .reverse else {
state.preview.lastSearch != .reverse
else {
state.preview.editorPosition = Marked(
mark: state.preview.editorPosition.mark,
payload: position.payload

View File

@ -4,16 +4,14 @@
*/
import Cocoa
import RxSwift
import PureLayout
import WebKit
import os
import NvimView
import os
import PureLayout
import RxSwift
import WebKit
class MarkdownTool: NSView, UiComponent, WKNavigationDelegate {
enum Action {
case refreshNow
case reverseSearch(to: Position)
@ -84,7 +82,8 @@ class MarkdownTool: NSView, UiComponent, WKNavigationDelegate {
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
if state.viewToBeFocused != nil,
case .markdownPreview = state.viewToBeFocused! {
case .markdownPreview = state.viewToBeFocused!
{
self.beFirstResponder()
}
@ -92,9 +91,10 @@ class MarkdownTool: NSView, UiComponent, WKNavigationDelegate {
self.automaticReverseMenuItem.boolState = state.previewTool.isReverseSearchAutomatically
self.refreshOnWriteMenuItem.boolState = state.previewTool.isRefreshOnWrite
if state.preview.status == .markdown
&& state.previewTool.isForwardSearchAutomatically
&& state.preview.editorPosition.hasDifferentMark(as: self.editorPosition) {
if state.preview.status == .markdown,
state.previewTool.isForwardSearchAutomatically,
state.preview.editorPosition.hasDifferentMark(as: self.editorPosition)
{
self.forwardSearch(position: state.preview.editorPosition.payload)
}
@ -133,18 +133,23 @@ class MarkdownTool: NSView, UiComponent, WKNavigationDelegate {
private func addViews() {
self.webview.navigationDelegate = self
self.userContentController.add(webviewMessageHandler, name: "com_vimr_tools_preview_markdown")
self.userContentController.add(
self.webviewMessageHandler,
name: "com_vimr_tools_preview_markdown"
)
self.webview.configureForAutoLayout()
self.addSubview(self.webview)
self.webview.autoPinEdgesToSuperviewEdges()
}
func webView(_: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
func webView(_: WKWebView, didFailProvisionalNavigation _: WKNavigation!,
withError error: Error)
{
self.log.error("ERROR preview component's webview: \(error)")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
func webView(_: WKWebView, didFinish _: WKNavigation!) {
self.webview.evaluateJavaScript("document.body.scrollTop = \(self.scrollTop)")
}
@ -165,33 +170,45 @@ class MarkdownTool: NSView, UiComponent, WKNavigationDelegate {
private let userContentController = WKUserContentController()
private let webviewMessageHandler = WebviewMessageHandler()
private let automaticForwardMenuItem = NSMenuItem(title: "Automatic Forward Search",
action: nil,
keyEquivalent: "")
private let automaticReverseMenuItem = NSMenuItem(title: "Automatic Reverse Search",
action: nil,
keyEquivalent: "")
private let refreshOnWriteMenuItem = NSMenuItem(title: "Refresh on Write", action: nil, keyEquivalent: "")
private let automaticForwardMenuItem = NSMenuItem(
title: "Automatic Forward Search",
action: nil,
keyEquivalent: ""
)
private let automaticReverseMenuItem = NSMenuItem(
title: "Automatic Reverse Search",
action: nil,
keyEquivalent: ""
)
private let refreshOnWriteMenuItem = NSMenuItem(
title: "Refresh on Write",
action: nil,
keyEquivalent: ""
)
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui
)
required init?(coder: NSCoder) {
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func forwardSearch(position: Position) {
self.webview.evaluateJavaScript("scrollToPosition(\(position.row), \(position.column));") { result, error in
if let scrollTop = result as? Int {
self.scrollTop = scrollTop
self.webview
.evaluateJavaScript("scrollToPosition(\(position.row), \(position.column));") { result, _ in
if let scrollTop = result as? Int {
self.scrollTop = scrollTop
}
}
}
}
}
// MARK: - Actions
extension MarkdownTool {
extension MarkdownTool {
@objc func refreshNowAction(_: Any?) {
self.emit(UuidAction(uuid: self.uuid, action: .refreshNow))
}
@ -205,11 +222,13 @@ extension MarkdownTool {
}
@objc func automaticForwardSearchAction(_ sender: NSMenuItem) {
self.emit(UuidAction(uuid: self.uuid, action: .setAutomaticForwardSearch(to: !sender.boolState)))
self
.emit(UuidAction(uuid: self.uuid, action: .setAutomaticForwardSearch(to: !sender.boolState)))
}
@objc func automaticReverseSearchAction(_ sender: NSMenuItem) {
self.emit(UuidAction(uuid: self.uuid, action: .setAutomaticReverseSearch(to: !sender.boolState)))
self
.emit(UuidAction(uuid: self.uuid, action: .setAutomaticReverseSearch(to: !sender.boolState)))
}
@objc func refreshOnWriteAction(_ sender: NSMenuItem) {
@ -218,9 +237,8 @@ extension MarkdownTool {
}
private class WebviewMessageHandler: NSObject, WKScriptMessageHandler {
var source: Observable<(Position, Int)> {
return self.subject.asObservable()
self.subject.asObservable()
}
deinit {
@ -235,7 +253,7 @@ private class WebviewMessageHandler: NSObject, WKScriptMessageHandler {
guard let lineBegin = msgBody["lineBegin"],
let columnBegin = msgBody["columnBegin"],
let scrollTop = msgBody["scrollTop"]
else {
else {
return
}

View File

@ -6,7 +6,6 @@
import Foundation
class MarkdownToolReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MarkdownTool.Action>
@ -18,19 +17,17 @@ class MarkdownToolReducer: ReducerType {
var state = tuple.state
switch tuple.action.payload {
case let .setAutomaticReverseSearch(to:value):
case let .setAutomaticReverseSearch(to: value):
state.previewTool.isReverseSearchAutomatically = value
case let .setAutomaticForwardSearch(to:value):
case let .setAutomaticForwardSearch(to: value):
state.previewTool.isForwardSearchAutomatically = value
case let .setRefreshOnWrite(to:value):
case let .setRefreshOnWrite(to: value):
state.previewTool.isRefreshOnWrite = value
default:
return tuple
}
return (state, tuple.action, true)

View File

@ -6,7 +6,6 @@
import Cocoa
class OpenQuicklyFileViewRow: NSTableRowView {
override func drawSelection(in dirtyRect: NSRect) {
if self.isSelected {
NSColor.selectedControlColor.set()

View File

@ -7,7 +7,6 @@ import Foundation
import RxSwift
class OpenQuicklyReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = OpenQuicklyWindow.Action
@ -17,7 +16,6 @@ class OpenQuicklyReducer: ReducerType {
var appState = pair.state
switch pair.action {
case let .setUsesVcsIgnores(usesVcsIgnores):
guard let uuid = appState.currentMainWindowUuid else { return pair }
appState.mainWindows[uuid]?.usesVcsIgnores = usesVcsIgnores
@ -29,21 +27,17 @@ class OpenQuicklyReducer: ReducerType {
case .close:
appState.openQuickly.open = false
break
}
return (appState, pair.action, true)
}
class MainWindowReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = UuidAction<MainWindow.Action>
func typedReduce(_ pair: ReduceTuple) -> ReduceTuple {
switch pair.action.payload {
case .openQuickly:
var appState = pair.state
@ -56,7 +50,6 @@ class OpenQuicklyReducer: ReducerType {
default:
return pair
}
}
}

View File

@ -4,28 +4,27 @@
*/
import Cocoa
import RxSwift
import RxCocoa
import PureLayout
import os
import Commons
import os
import PureLayout
import RxCocoa
import RxSwift
class OpenQuicklyWindow: NSObject,
UiComponent,
NSWindowDelegate,
NSTextFieldDelegate,
NSTableViewDelegate {
UiComponent,
NSWindowDelegate,
NSTextFieldDelegate,
NSTableViewDelegate
{
typealias StateType = AppState
enum Action {
case setUsesVcsIgnores(Bool)
case open(URL)
case close
}
@objc dynamic private(set) var unsortedScoredUrls = [ScoredUrl]()
@objc private(set) dynamic var unsortedScoredUrls = [ScoredUrl]()
// Call this only when quitting
func cleanUp() {
@ -62,6 +61,7 @@ class OpenQuicklyWindow: NSObject,
}
// MARK: - Private
private let emit: (Action) -> Void
private let disposeBag = DisposeBag()
@ -83,8 +83,10 @@ class OpenQuicklyWindow: NSObject,
private let cwdControl = NSPathControl(forAutoLayout: ())
private let fileView = NSTableView.standardTableView()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.ui
)
private var window: NSWindow { self.windowController.window! }
@ -108,7 +110,7 @@ class OpenQuicklyWindow: NSObject,
let windowIsOpen = self.window.isKeyWindow
// The window is open and the user changed the setting
if self.usesVcsIgnores != curWinState.usesVcsIgnores && windowIsOpen {
if self.usesVcsIgnores != curWinState.usesVcsIgnores, windowIsOpen {
self.usesVcsIgnores = curWinState.usesVcsIgnores
self.useVcsIgnoresCheckBox.boolState = curWinState.usesVcsIgnores
@ -190,7 +192,7 @@ class OpenQuicklyWindow: NSObject,
}
private func endProgress() {
DispatchQueue.main.async {self.progressIndicator.stopAnimation(self) }
DispatchQueue.main.async { self.progressIndicator.stopAnimation(self) }
}
private func updateRootUrls(state: AppState) {
@ -298,10 +300,10 @@ class OpenQuicklyWindow: NSObject,
}
// MARK: - NSTableViewDelegate
extension OpenQuicklyWindow {
func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
return OpenQuicklyFileViewRow()
extension OpenQuicklyWindow {
func tableView(_: NSTableView, rowViewForRow _: Int) -> NSTableRowView? {
OpenQuicklyFileViewRow()
}
func tableView(_ tableView: NSTableView, viewFor _: NSTableColumn?, row: Int) -> NSView? {
@ -313,7 +315,7 @@ extension OpenQuicklyWindow {
)?.reset()
let cell = cachedCell ?? ImageAndTextTableCell(withIdentifier: "file-view-row")
guard let sortedUrls = self.scoredUrlsController.arrangedObjects as? Array<ScoredUrl> else {
guard let sortedUrls = self.scoredUrlsController.arrangedObjects as? [ScoredUrl] else {
self.log.error("Could not convert arranged objects to [ScoredUrl].")
return nil
}
@ -351,27 +353,26 @@ extension OpenQuicklyWindow {
}
// MARK: - NSTextFieldDelegate
extension OpenQuicklyWindow {
extension OpenQuicklyWindow {
func control(
_ control: NSControl,
textView: NSTextView,
_: NSControl,
textView _: NSTextView,
doCommandBy commandSelector: Selector
) -> Bool {
switch commandSelector {
case NSSelectorFromString("cancelOperation:"):
self.window.performClose(self)
return true
case NSSelectorFromString("insertNewline:"):
guard let sortedUrls = self.scoredUrlsController.arrangedObjects as? Array<ScoredUrl> else {
guard let sortedUrls = self.scoredUrlsController.arrangedObjects as? [ScoredUrl] else {
self.log.error("Could not convert arranged objects to [ScoredUrl].")
return true
}
let selectedRow = self.fileView.selectedRow
guard selectedRow >= 0 && selectedRow < sortedUrls.count else { return false }
guard selectedRow >= 0, selectedRow < sortedUrls.count else { return false }
self.emit(.open(sortedUrls[selectedRow].url))
self.window.performClose(self)
@ -387,7 +388,6 @@ extension OpenQuicklyWindow {
default:
return false
}
}
@ -410,8 +410,8 @@ extension OpenQuicklyWindow {
}
// MARK: - NSWindowDelegate
extension OpenQuicklyWindow {
extension OpenQuicklyWindow {
func windowShouldClose(_: NSWindow) -> Bool {
self.emit(.close)

View File

@ -8,7 +8,6 @@ import DictionaryCoding
import os
class PrefMiddleware: MiddlewareType {
typealias StateType = AppState
typealias ActionType = AnyAction
@ -27,7 +26,7 @@ class PrefMiddleware: MiddlewareType {
}
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
return { tuple in
{ tuple in
let result = reduce(tuple)
guard result.modified else {
@ -52,7 +51,7 @@ class PrefMiddleware: MiddlewareType {
notification.identifier = UUID().uuidString
notification.title = "No monospaced font"
notification.informativeText = "The font you selected\(newFontNameText) does not seem "
+ "to be a monospaced font. The rendering will most likely be broken."
+ "to be a monospaced font. The rendering will most likely be broken."
NSUserNotificationCenter.default.deliver(notification)
}
}
@ -73,12 +72,11 @@ class PrefMiddleware: MiddlewareType {
private var currentFont = NSFont.userFixedPitchFont(ofSize: 13)!
class MainWindowMiddleware: MiddlewareType {
typealias StateType = AppState
typealias ActionType = UuidAction<MainWindow.Action>
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
return { tuple in
{ tuple in
let result = reduce(tuple)
guard case .close = tuple.action.payload else {
@ -96,8 +94,10 @@ class PrefMiddleware: MiddlewareType {
}
}
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private let log = OSLog(
subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware
)
}
}

View File

@ -6,10 +6,9 @@
import Cocoa
class PrefPane: NSView {
// Return true to place this to the upper left corner when the scroll view is bigger than this view.
override var isFlipped: Bool {
return true
true
}
var displayName: String {
@ -17,7 +16,7 @@ class PrefPane: NSView {
}
var pinToContainer: Bool {
return false
false
}
func paneWillAppear() {
@ -30,19 +29,19 @@ class PrefPane: NSView {
}
// MARK: - Control Utils
extension PrefPane {
extension PrefPane {
func paneTitleTextField(title: String) -> NSTextField {
let field = NSTextField.defaultTitleTextField()
field.font = NSFont.boldSystemFont(ofSize: 16)
field.alignment = .left;
field.alignment = .left
field.stringValue = title
return field
}
func titleTextField(title: String) -> NSTextField {
let field = NSTextField.defaultTitleTextField()
field.alignment = .right;
field.alignment = .right
field.stringValue = title
return field
}

View File

@ -7,21 +7,22 @@ import Cocoa
import NvimView
class PrefUtils {
static func value<T>(from dict: [String: Any], for key: String) -> T? {
return dict[key] as? T
dict[key] as? T
}
static func value<T>(from dict: [String: Any], for key: String, default defaultValue: T) -> T {
return dict[key] as? T ?? defaultValue
dict[key] as? T ?? defaultValue
}
static func dict(from dict: [String: Any], for key: String) -> [String: Any]? {
return dict[key] as? [String: Any]
dict[key] as? [String: Any]
}
static func float(from dict: [String: Any], for key: String, default defaultValue: Float) -> Float {
return (dict[key] as? NSNumber)?.floatValue ?? defaultValue
static func float(from dict: [String: Any], for key: String,
default defaultValue: Float) -> Float
{
(dict[key] as? NSNumber)?.floatValue ?? defaultValue
}
static func float(from dict: [String: Any], for key: String) -> Float? {
@ -41,15 +42,17 @@ class PrefUtils {
}
static func bool(from dict: [String: Any], for key: String, default defaultValue: Bool) -> Bool {
return (dict[key] as? NSNumber)?.boolValue ?? defaultValue
(dict[key] as? NSNumber)?.boolValue ?? defaultValue
}
static func string(from dict: [String: Any], for key: String) -> String? {
return dict[key] as? String
dict[key] as? String
}
static func string(from dict: [String: Any], for key: String, default defaultValue: String) -> String {
return dict[key] as? String ?? defaultValue
static func string(from dict: [String: Any], for key: String,
default defaultValue: String) -> String
{
dict[key] as? String ?? defaultValue
}
static func saneFont(_ fontName: String, fontSize: CGFloat) -> NSFont {
@ -66,19 +69,19 @@ class PrefUtils {
static func saneLinespacing(_ fLinespacing: Float) -> CGFloat {
let linespacing = fLinespacing.cgf
guard linespacing >= NvimView.minLinespacing && linespacing <= NvimView.maxLinespacing else {
guard linespacing >= NvimView.minLinespacing, linespacing <= NvimView.maxLinespacing else {
return NvimView.defaultLinespacing
}
return linespacing
}
static func saneCharacterspacing(_ fCharacterspacing: Float) -> CGFloat {
let characterspacing = fCharacterspacing.cgf
guard characterspacing >= 0.0 else {
return NvimView.defaultCharacterspacing
}
return characterspacing
}
}

View File

@ -4,18 +4,17 @@
*/
import Cocoa
import RxSwift
import PureLayout
import RxSwift
class PrefWindow: NSObject,
UiComponent,
NSWindowDelegate,
NSTableViewDataSource, NSTableViewDelegate {
UiComponent,
NSWindowDelegate,
NSTableViewDataSource, NSTableViewDelegate
{
typealias StateType = AppState
enum Action {
case close
}
@ -66,7 +65,7 @@ class PrefWindow: NSObject,
private let windowController: NSWindowController
private var window: NSWindow {
return self.windowController.window!
self.windowController.window!
}
private let categoryView = NSTableView.standardSourceListTableView()
@ -76,7 +75,7 @@ class PrefWindow: NSObject,
private let panes: [PrefPane]
private var currentPane: PrefPane {
get {
return self.paneContainer.documentView as! PrefPane
self.paneContainer.documentView as! PrefPane
}
set {
@ -124,8 +123,8 @@ class PrefWindow: NSObject,
}
// MARK: - NSWindowDelegate
extension PrefWindow {
extension PrefWindow {
func windowShouldClose(_: NSWindow) -> Bool {
self.emit(.close)
@ -138,20 +137,24 @@ extension PrefWindow {
}
// MARK: - NSTableViewDataSource
extension PrefWindow {
extension PrefWindow {
@objc(numberOfRowsInTableView:) func numberOfRows(in _: NSTableView) -> Int {
return self.panes.count
self.panes.count
}
@objc(tableView: objectValueForTableColumn:row:) func tableView(_: NSTableView, objectValueFor _: NSTableColumn?, row: Int) -> Any? {
return self.panes[row].displayName
@objc(tableView: objectValueForTableColumn:row:) func tableView(
_: NSTableView,
objectValueFor _: NSTableColumn?,
row: Int
) -> Any? {
self.panes[row].displayName
}
}
// MARK: - NSTableViewDelegate
extension PrefWindow {
extension PrefWindow {
func tableViewSelectionDidChange(_: Notification) {
let idx = self.categoryView.selectedRow
self.panes[idx].paneWillAppear()

View File

@ -6,7 +6,6 @@
import Foundation
class PrefWindowReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = PrefWindow.Action
@ -14,10 +13,8 @@ class PrefWindowReducer: ReducerType {
var state = pair.state
switch pair.action {
case .close:
state.preferencesOpen = Marked(false)
}
return (state, pair.action, true)

View File

@ -6,7 +6,6 @@
import Foundation
class Resources {
static let resourceUrl = Bundle.main.resourceURL!
static let previewUrl = resourceUrl.appendingPathComponent("preview")

View File

@ -6,7 +6,6 @@
import Foundation
class RpcAppearanceEpic: EpicType {
typealias StateType = AppState
typealias ActionType = UuidAction<MainWindow.Action>
typealias EmitActionType = AppearancePref.Action
@ -18,23 +17,21 @@ class RpcAppearanceEpic: EpicType {
func typedApply(
_ reduce: @escaping TypedActionReduceFunction
) -> TypedActionReduceFunction {
return { tuple in
{ tuple in
let result = reduce(tuple)
switch tuple.action.payload {
case .setFont(let font):
case let .setFont(font):
self.emit(.setFont(font))
case .setLinespacing(let linespacing):
case let .setLinespacing(linespacing):
self.emit(.setLinespacing(linespacing))
case .setCharacterspacing(let characterspacing):
case let .setCharacterspacing(characterspacing):
self.emit(.setCharacterspacing(characterspacing))
default:
break
}
return result

View File

@ -6,7 +6,6 @@
import Foundation
enum RpcEvent: String, CaseIterable {
static let prefix = "com.qvacua.vimr.rpc-events"
case makeSessionTemporary = "com.qvacua.vimr.rpc-events.make-session-temporary"

View File

@ -6,8 +6,7 @@
import Cocoa
class ShortcutItem: NSObject, Comparable {
static func <(lhs: ShortcutItem, rhs: ShortcutItem) -> Bool { lhs.title < rhs.title }
static func < (lhs: ShortcutItem, rhs: ShortcutItem) -> Bool { lhs.title < rhs.title }
@objc dynamic var title: String
@objc dynamic var isLeaf: Bool
@ -19,11 +18,11 @@ class ShortcutItem: NSObject, Comparable {
var isContainer: Bool { !self.isLeaf }
override var description: String {
"<ShortcutItem: \(title), " +
"id: '\(self.identifier ?? "")', " +
"isLeaf: \(self.isLeaf), " +
"childrenCount: \(self.children?.count ?? -1)" +
">"
"<ShortcutItem: \(self.title), " +
"id: '\(self.identifier ?? "")', " +
"isLeaf: \(self.isLeaf), " +
"childrenCount: \(self.children?.count ?? -1)" +
">"
}
let item: NSMenuItem?

View File

@ -9,10 +9,10 @@ import RxSwift
import ShortcutRecorder
class ShortcutsPref: PrefPane,
UiComponent,
NSOutlineViewDelegate,
RecorderControlDelegate {
UiComponent,
NSOutlineViewDelegate,
RecorderControlDelegate
{
typealias StateType = AppState
@objc dynamic var content = [ShortcutItem]()
@ -21,7 +21,7 @@ class ShortcutsPref: PrefPane,
override var pinToContainer: Bool { true }
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
required init(source _: Observable<StateType>, emitter _: ActionEmitter, state _: StateType) {
// We know that the identifier is not empty.
let shortcutSuiteName = Bundle.main.bundleIdentifier! + ".menuitems"
self.shortcutsUserDefaults = UserDefaults(suiteName: shortcutSuiteName)
@ -33,14 +33,15 @@ class ShortcutsPref: PrefPane,
super.init(frame: .zero)
if let version = self.shortcutsUserDefaults?.integer(forKey: defaultsVersionKey),
version > defaultsVersion {
version > defaultsVersion
{
let alert = NSAlert()
alert.alertStyle = .warning
alert.messageText = "Incompatible Defaults for Shortcuts"
alert.informativeText = "The stored defaults for shortcuts are not compatible with "
+ "this version of VimR. You can delete the stored defaults "
+ "by executing 'defaults delete com.qvacua.VimR.menuitems' "
+ "in Terminal."
+ "this version of VimR. You can delete the stored defaults "
+ "by executing 'defaults delete com.qvacua.VimR.menuitems' "
+ "in Terminal."
alert.runModal()
return
}
@ -59,7 +60,8 @@ class ShortcutsPref: PrefPane,
self.shortcutList.expandItem(nil, expandChildren: true)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
private let shortcutList = NSOutlineView.standardOutlineView()
private let shortcutScrollView = NSScrollView.standardScrollView()
@ -126,7 +128,7 @@ class ShortcutsPref: PrefPane,
private func traverseMenuItems(with fn: (String, NSMenuItem) -> Void) {
var queue = self.shortcutItemsRoot.children ?? []
while (!queue.isEmpty) {
while !queue.isEmpty {
guard let item = queue.popLast() else { break }
if item.isContainer, let children = item.children {
queue.append(contentsOf: children)
@ -168,18 +170,18 @@ class ShortcutsPref: PrefPane,
shortcutItem: ShortcutItem(title: $0.title, isLeaf: false, item: $0)
)
}
while (!queue.isEmpty) {
while !queue.isEmpty {
guard let entry = queue.popLast() else { break }
if !entry.shortcutItem.isLeaf
|| entry.shortcutItem.identifier?.hasPrefix("com.qvacua.vimr.menuitems.") == true {
|| entry.shortcutItem.identifier?.hasPrefix("com.qvacua.vimr.menuitems.") == true
{
entry.parent.children?.append(entry.shortcutItem)
}
if entry.shortcutItem.isContainer,
let childMenuItems = entry.shortcutItem.item?.submenu?.items {
let childMenuItems = entry.shortcutItem.item?.submenu?.items
{
let shortcutChildItems = childMenuItems
.filter { !$0.title.isEmpty }
.map { menuItem in
@ -233,9 +235,9 @@ class ShortcutsPref: PrefPane,
}
// MARK: - Actions
extension ShortcutsPref {
@objc func resetToDefault(_ sender: NSButton) {
extension ShortcutsPref {
@objc func resetToDefault(_: NSButton) {
guard let window = self.window else { return }
let alert = NSAlert()
@ -260,8 +262,8 @@ extension ShortcutsPref {
}
// MARK: - NSOutlineViewDelegate
extension ShortcutsPref {
extension ShortcutsPref {
private func isUppercase(_ str: String) -> Bool {
for c in str.unicodeScalars {
if !CharacterSet.uppercaseLetters.contains(c) { return false }
@ -270,7 +272,7 @@ extension ShortcutsPref {
return true
}
func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? {
func outlineView(_: NSOutlineView, rowViewForItem _: Any) -> NSTableRowView? {
let view = self.shortcutList.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("shortcut-row-view"),
owner: self
@ -279,7 +281,7 @@ extension ShortcutsPref {
return view
}
func outlineView(_: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
func outlineView(_: NSOutlineView, viewFor _: NSTableColumn?, item: Any) -> NSView? {
let cellView = self.shortcutList.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("shortcut-cell-view"),
owner: self
@ -306,7 +308,7 @@ extension ShortcutsPref {
return cellView
}
func outlineView(_: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat { 28 }
func outlineView(_: NSOutlineView, heightOfRowByItem _: Any) -> CGFloat { 28 }
private func areShortcutsEqual(_ identifier: String) -> Bool {
guard let dataFromDefaults = self.shortcutsDefaultsController.value(
@ -324,9 +326,9 @@ extension ShortcutsPref {
}
// MARK: - SRRecorderControlDelegate
extension ShortcutsPref {
func recorderControlDidEndRecording(_ sender: RecorderControl) {
extension ShortcutsPref {
func recorderControlDidEndRecording(_: RecorderControl) {
self.treeController.rearrangeObjects()
}
}
@ -335,7 +337,6 @@ private let defaultsVersionKey = "version"
private let defaultsVersion = 337
private class DataToKeyEquivalentTransformer: ValueTransformer {
override func transformedValue(_ value: Any?) -> Any? {
guard let shortcut = ValueTransformer
.keyedUnarchiveFromDataTransformer
@ -346,7 +347,6 @@ private class DataToKeyEquivalentTransformer: ValueTransformer {
}
private class DataToKeyEquivalentModifierMaskTransformer: ValueTransformer {
override func transformedValue(_ value: Any?) -> Any? {
guard let shortcut = ValueTransformer
.keyedUnarchiveFromDataTransformer

View File

@ -7,19 +7,18 @@ import Cocoa
import ShortcutRecorder
class ShortcutTableRow: NSTableRowView {
init(withIdentifier identifier: String) {
super.init(frame: .zero)
self.identifier = NSUserInterfaceItemIdentifier(identifier)
}
required init?(coder: NSCoder) {
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class ShortcutTableCell: NSTableCellView {
static let font = NSFont.systemFont(ofSize: 13)
static let boldFont = NSFont.boldSystemFont(ofSize: 13)
@ -117,6 +116,6 @@ class ShortcutTableCell: NSTableCellView {
private let shortcutRecorder = RecorderControl(forAutoLayout: ())
private let _textField = NSTextField(forAutoLayout: ())
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
}

View File

@ -4,24 +4,21 @@
*/
import Cocoa
import Commons
import NvimView
import RxSwift
import Commons
import Workspace
struct AppState: Codable {
enum AfterLastWindowAction: String, Codable {
case doNothing = "do-nothing"
case hide = "hide"
case quit = "quit"
case hide
case quit
}
static let `default` = AppState()
enum CodingKeys: String, CodingKey {
case openNewMainWindowOnLaunch = "open-new-window-when-launching"
case openNewMainWindowOnReactivation = "open-new-window-on-reactivation"
case afterLastWindowAction = "after-last-window-action"
@ -56,33 +53,44 @@ struct AppState: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.openNewMainWindowOnLaunch = try container.decode(forKey: .openNewMainWindowOnLaunch,
default: AppState.default.openNewMainWindowOnLaunch)
self.openNewMainWindowOnReactivation = try container.decode(
forKey: .openNewMainWindowOnReactivation, default: AppState.default.openNewMainWindowOnReactivation
self.openNewMainWindowOnLaunch = try container.decode(
forKey: .openNewMainWindowOnLaunch,
default: AppState.default
.openNewMainWindowOnLaunch
)
self.openNewMainWindowOnReactivation = try container.decode(
forKey: .openNewMainWindowOnReactivation,
default: AppState.default.openNewMainWindowOnReactivation
)
self.afterLastWindowAction = try container.decode(
forKey: .afterLastWindowAction,
default: .doNothing
)
self.useSnapshotUpdate = try container.decode(
forKey: .useSnapshotUpdate,
default: AppState.default.useSnapshotUpdate
)
self.afterLastWindowAction = try container.decode(forKey: .afterLastWindowAction, default: .doNothing)
self.useSnapshotUpdate = try container.decode(forKey: .useSnapshotUpdate,
default: AppState.default.useSnapshotUpdate)
self.openQuickly = try container.decode(forKey: .openQuickly, default: OpenQuicklyWindow.State.default)
self.mainWindowTemplate = try container.decode(forKey: .mainWindowTemplate, default: MainWindow.State.default)
self.openQuickly = try container.decode(
forKey: .openQuickly,
default: OpenQuicklyWindow.State.default
)
self.mainWindowTemplate = try container.decode(
forKey: .mainWindowTemplate,
default: MainWindow.State.default
)
}
// Use generated encode(to:)
private init() {
}
private init() {}
}
extension OpenQuicklyWindow {
struct State: Codable {
static let `default` = State()
enum CodingKeys: String, CodingKey {
case defaultUsesVcsIgnore = "default-uses-vcs-ignores"
}
@ -103,17 +111,14 @@ extension OpenQuicklyWindow {
try container.encode(self.defaultUsesVcsIgnores, forKey: .defaultUsesVcsIgnore)
}
private init() {
}
private init() {}
}
}
struct PreviewState {
static let `default` = PreviewState()
enum Status {
case none
case notSaved
case error
@ -121,7 +126,6 @@ struct PreviewState {
}
enum SearchAction {
case none
case forward
case reverse
@ -160,7 +164,6 @@ struct PreviewState {
}
struct HtmlPreviewState {
static let `default` = HtmlPreviewState()
var htmlFile: URL?
@ -168,11 +171,9 @@ struct HtmlPreviewState {
}
struct AppearanceState: Codable {
static let `default` = AppearanceState()
enum CodingKeys: String, CodingKey {
case usesTheme = "uses-theme"
case showsFileIcon = "shows-file-icon"
case editorFontName = "editor-font-name"
@ -196,15 +197,23 @@ struct AppearanceState: Codable {
if let fontName = try container.decodeIfPresent(String.self, forKey: .editorFontName),
let fontSize = try container.decodeIfPresent(Float.self, forKey: .editorFontSize),
let font = NSFont(name: fontName, size: fontSize.cgf) {
let font = NSFont(name: fontName, size: fontSize.cgf)
{
self.font = font
} else {
self.font = NvimView.defaultFont
}
self.linespacing = (try container.decodeIfPresent(Float.self, forKey: .editorLinespacing) ?? 1.0).cgf
self.characterspacing = (try container.decodeIfPresent(Float.self, forKey: .editorCharacterspacing) ?? 1.0).cgf
self.usesLigatures = try container.decodeIfPresent(Bool.self, forKey: .editorUsesLigatures) ?? true
self
.linespacing = (try container.decodeIfPresent(Float.self, forKey: .editorLinespacing) ?? 1.0)
.cgf
self
.characterspacing = (
try container
.decodeIfPresent(Float.self, forKey: .editorCharacterspacing) ?? 1.0
).cgf
self.usesLigatures = try container
.decodeIfPresent(Bool.self, forKey: .editorUsesLigatures) ?? true
self.usesTheme = try container.decodeIfPresent(Bool.self, forKey: .usesTheme) ?? true
self.showsFileIcon = try container.decodeIfPresent(Bool.self, forKey: .showsFileIcon) ?? true
@ -222,14 +231,11 @@ struct AppearanceState: Codable {
try container.encode(self.usesLigatures, forKey: .editorUsesLigatures)
}
private init() {
}
private init() {}
}
extension MainWindow {
struct State: Codable {
static let `default` = State(isAllToolsVisible: true, isToolButtonsVisible: true)
static let defaultTools: [MainWindow.Tools: WorkspaceToolState] = [
@ -239,7 +245,8 @@ extension MainWindow {
.htmlPreview: WorkspaceToolState(location: .right, dimension: 500, open: false),
]
static let orderedDefault: [MainWindow.Tools] = [.fileBrowser, .buffersList, .preview, .htmlPreview]
static let orderedDefault: [MainWindow.Tools] = [.fileBrowser, .buffersList, .preview,
.htmlPreview]
var isAllToolsVisible = true
var isToolButtonsVisible = true
@ -303,12 +310,11 @@ extension MainWindow {
}
enum CodingKeys: String, CodingKey {
case allToolsVisible = "is-all-tools-visible"
case toolButtonsVisible = "is-tool-buttons-visible"
case orderedTools = "ordered-tools"
case activeTools = "active-tools"
case frame = "frame"
case frame
case isLeftOptionMeta = "is-left-option-meta"
case isRightOptionMeta = "is-right-option-meta"
@ -319,7 +325,7 @@ extension MainWindow {
case drawsParallel = "draws-parallel"
case isShowHidden = "is-show-hidden"
case appearance = "appearance"
case appearance
case workspaceTools = "workspace-tool"
case previewTool = "preview-tool"
}
@ -327,34 +333,58 @@ extension MainWindow {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.isLeftOptionMeta = try container.decode(forKey: .isLeftOptionMeta, default: State.default.isLeftOptionMeta)
self.isRightOptionMeta = try container.decode(forKey: .isRightOptionMeta,
default: State.default.isRightOptionMeta)
self.useInteractiveZsh = try container.decode(forKey: .useInteractiveZsh,
default: State.default.useInteractiveZsh)
self.trackpadScrollResistance = try container.decode(forKey: .trackpadScrollResistance,
default: State.default.trackpadScrollResistance)
self.useLiveResize = try container.decode(forKey: .useLiveResize, default: State.default.useLiveResize)
self.drawsParallel = try container.decode(forKey: .drawsParallel, default: State.default.drawsParallel)
self.isLeftOptionMeta = try container.decode(
forKey: .isLeftOptionMeta,
default: State.default.isLeftOptionMeta
)
self.isRightOptionMeta = try container.decode(
forKey: .isRightOptionMeta,
default: State.default.isRightOptionMeta
)
self.useInteractiveZsh = try container.decode(
forKey: .useInteractiveZsh,
default: State.default.useInteractiveZsh
)
self.trackpadScrollResistance = try container.decode(
forKey: .trackpadScrollResistance,
default: State.default
.trackpadScrollResistance
)
self.useLiveResize = try container.decode(
forKey: .useLiveResize,
default: State.default.useLiveResize
)
self.drawsParallel = try container.decode(
forKey: .drawsParallel,
default: State.default.drawsParallel
)
if let frameRawValue = try container.decodeIfPresent(String.self, forKey: .frame) {
self.frame = NSRectFromString(frameRawValue)
} else {
self.frame = CGRect(x: 100, y: 100, width: 600, height: 400)
}
self.isAllToolsVisible = try container.decode(forKey: .allToolsVisible, default: State.default.isAllToolsVisible)
self.isToolButtonsVisible = try container.decode(forKey: .toolButtonsVisible,
default: State.default.isToolButtonsVisible)
self.isAllToolsVisible = try container.decode(
forKey: .allToolsVisible,
default: State.default.isAllToolsVisible
)
self.isToolButtonsVisible = try container.decode(
forKey: .toolButtonsVisible,
default: State.default.isToolButtonsVisible
)
self.appearance = try container.decode(forKey: .appearance, default: State.default.appearance)
self.orderedTools = try container.decode(forKey: .orderedTools, default: State.default.orderedTools)
self.orderedTools = try container.decode(
forKey: .orderedTools,
default: State.default.orderedTools
)
let missingOrderedTools = MainWindow.Tools.all.subtracting(self.orderedTools)
self.orderedTools.append(contentsOf: missingOrderedTools)
// See [1]
let rawActiveTools: [String: Bool] = try container.decode(forKey: .activeTools, default: [:])
self.activeTools = rawActiveTools.flatMapToDict { (key, value) in
self.activeTools = rawActiveTools.flatMapToDict { key, value in
guard let toolId = MainWindow.Tools(rawValue: key) else {
return nil
}
@ -364,8 +394,9 @@ extension MainWindow {
let missingActiveTools = MainWindow.Tools.all.subtracting(self.activeTools.keys)
missingActiveTools.forEach { self.activeTools[$0] = true }
let rawTools: [String: WorkspaceToolState] = try container.decode(forKey: .workspaceTools, default: [:])
self.tools = rawTools.flatMapToDict { (key, value) in
let rawTools: [String: WorkspaceToolState] = try container
.decode(forKey: .workspaceTools, default: [:])
self.tools = rawTools.flatMapToDict { key, value in
guard let tool = MainWindow.Tools(rawValue: key) else {
return nil
}
@ -377,9 +408,15 @@ extension MainWindow {
self.tools[missingTool] = MainWindow.State.defaultTools[missingTool]!
}
self.previewTool = try container.decode(forKey: .previewTool, default: State.default.previewTool)
self.fileBrowserShowHidden = try container.decode(forKey: .isShowHidden,
default: State.default.fileBrowserShowHidden)
self.previewTool = try container.decode(
forKey: .previewTool,
default: State.default.previewTool
)
self.fileBrowserShowHidden = try container.decode(
forKey: .isShowHidden,
default: State.default
.fileBrowserShowHidden
)
}
func encode(to encoder: Encoder) throws {
@ -397,10 +434,14 @@ extension MainWindow {
try container.encode(self.fileBrowserShowHidden, forKey: .isShowHidden)
// See [1]
try container.encode(Dictionary(uniqueKeysWithValues: self.tools.map { k, v in (k.rawValue, v) }),
forKey: .workspaceTools)
try container.encode(Dictionary(uniqueKeysWithValues: self.activeTools.map { k, v in (k.rawValue, v) }),
forKey: .activeTools)
try container.encode(
Dictionary(uniqueKeysWithValues: self.tools.map { k, v in (k.rawValue, v) }),
forKey: .workspaceTools
)
try container.encode(
Dictionary(uniqueKeysWithValues: self.activeTools.map { k, v in (k.rawValue, v) }),
forKey: .activeTools
)
try container.encode(self.appearance, forKey: .appearance)
try container.encode(self.orderedTools, forKey: .orderedTools)
@ -410,14 +451,12 @@ extension MainWindow {
}
struct WorkspaceToolState: Codable {
static let `default` = WorkspaceToolState()
enum CodingKeys: String, CodingKey {
case location = "location"
case `open` = "is-visible"
case dimension = "dimension"
case location
case open = "is-visible"
case dimension
}
var location = WorkspaceBarLocation.left
@ -443,8 +482,7 @@ struct WorkspaceToolState: Codable {
// Use generated encode(to:)
private init() {
}
private init() {}
init(location: WorkspaceBarLocation, dimension: CGFloat, open: Bool) {
self.location = location
@ -454,13 +492,10 @@ struct WorkspaceToolState: Codable {
}
extension MarkdownTool {
struct State: Codable {
static let `default` = State()
enum CodingKeys: String, CodingKey {
case forwardSearchAutomatically = "is-forward-search-automatically"
case reverseSearchAutomatically = "is-reverse-search-automatically"
case refreshOnWrite = "is-refresh-on-write"
@ -470,17 +505,25 @@ extension MarkdownTool {
var isReverseSearchAutomatically = false
var isRefreshOnWrite = true
private init() {
}
private init() {}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.isForwardSearchAutomatically = try container.decode(forKey: .forwardSearchAutomatically,
default: State.default.isForwardSearchAutomatically)
self.isReverseSearchAutomatically = try container.decode(forKey: .reverseSearchAutomatically,
default: State.default.isReverseSearchAutomatically)
self.isRefreshOnWrite = try container.decode(forKey: .refreshOnWrite, default: State.default.isRefreshOnWrite)
self.isForwardSearchAutomatically = try container.decode(
forKey: .forwardSearchAutomatically,
default: State.default
.isForwardSearchAutomatically
)
self.isReverseSearchAutomatically = try container.decode(
forKey: .reverseSearchAutomatically,
default: State.default
.isReverseSearchAutomatically
)
self.isRefreshOnWrite = try container.decode(
forKey: .refreshOnWrite,
default: State.default.isRefreshOnWrite
)
}
func encode(to encoder: Encoder) throws {
@ -493,10 +536,9 @@ extension MarkdownTool {
}
}
fileprivate extension KeyedDecodingContainer where K: CodingKey {
func decode<T: Decodable>(forKey key: K, `default`: T) throws -> T {
return try self.decodeIfPresent(T.self, forKey: key) ?? `default`
private extension KeyedDecodingContainer where K: CodingKey {
func decode<T: Decodable>(forKey key: K, default: T) throws -> T {
try self.decodeIfPresent(T.self, forKey: key) ?? `default`
}
}

View File

@ -4,23 +4,23 @@
*/
import Cocoa
import NvimView
import Commons
import NvimView
func changeTheme(themePrefChanged: Bool, themeChanged: Bool, usesTheme: Bool,
forTheme: () -> Void, forDefaultTheme: () -> Void) -> Bool {
if themePrefChanged && usesTheme {
forTheme: () -> Void, forDefaultTheme: () -> Void) -> Bool
{
if themePrefChanged, usesTheme {
forTheme()
return true
}
if themePrefChanged && !usesTheme {
if themePrefChanged, !usesTheme {
forDefaultTheme()
return true
}
if !themePrefChanged && themeChanged && usesTheme {
if !themePrefChanged, themeChanged, usesTheme {
forTheme()
return true
}
@ -29,7 +29,6 @@ func changeTheme(themePrefChanged: Bool, themeChanged: Bool, usesTheme: Bool,
}
struct Theme: CustomStringConvertible {
static let `default` = Theme()
var foreground = NSColor.textColor
@ -53,11 +52,11 @@ struct Theme: CustomStringConvertible {
var cssCodeBackgroundColor = NSColor(hex: "1b1f23")!
public var description: String {
return "Theme<" +
"fg: \(self.foreground.hex), bg: \(self.background.hex), " +
"hl-fg: \(self.highlightForeground.hex), hl-bg: \(self.highlightBackground.hex)" +
"dir-fg: \(self.directoryForeground.hex)" +
">"
"Theme<" +
"fg: \(self.foreground.hex), bg: \(self.background.hex), " +
"hl-fg: \(self.highlightForeground.hex), hl-bg: \(self.highlightBackground.hex)" +
"dir-fg: \(self.directoryForeground.hex)" +
">"
}
init() {}

View File

@ -7,14 +7,12 @@ import Cocoa
import NvimView
import PureLayout
protocol ThemedView: class {
protocol ThemedView: AnyObject {
var theme: Theme { get }
var lastThemeMark: Token { get }
}
class ThemedTableRow: NSTableRowView {
weak var triangleView: NSButton?
var themeToken: Token
@ -34,11 +32,11 @@ class ThemedTableRow: NSTableRowView {
}
}
open override func drawBackground(in dirtyRect: NSRect) {
override open func drawBackground(in dirtyRect: NSRect) {
if let cell = self.view(atColumn: 0) as? ThemedTableCell {
if cell.isDir {
cell.textField?.textColor
= self.themedView?.theme.directoryForeground ?? Theme.default.directoryForeground
= self.themedView?.theme.directoryForeground ?? Theme.default.directoryForeground
} else {
cell.textField?.textColor = self.themedView?.theme.foreground ?? Theme.default.foreground
}
@ -51,7 +49,7 @@ class ThemedTableRow: NSTableRowView {
override func drawSelection(in dirtyRect: NSRect) {
if let cell = self.view(atColumn: 0) as? ThemedTableCell {
cell.textField?.textColor
= self.themedView?.theme.highlightForeground ?? Theme.default.highlightForeground
= self.themedView?.theme.highlightForeground ?? Theme.default.highlightForeground
}
self.themedView?.theme.highlightBackground.set()
@ -60,12 +58,13 @@ class ThemedTableRow: NSTableRowView {
private weak var themedView: ThemedView?
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
class ThemedTableCell: NSTableCellView {
// MARK: - API
static let font = NSFont.systemFont(ofSize: 12)
static let widthWithoutText = (2 + 16 + 4 + 2).cgf
@ -166,5 +165,6 @@ class ThemedTableCell: NSTableCellView {
private let _textField = NSTextField(forAutoLayout: ())
private let _imageView = NSImageView(forAutoLayout: ())
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@available(*, unavailable)
required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
}

View File

@ -8,20 +8,18 @@ import PureLayout
import RxSwift
class ToolsPref: PrefPane, UiComponent {
typealias StateType = AppState
enum Action {
case setActiveTools([MainWindow.Tools: Bool])
}
override var displayName: String {
return "Tools"
"Tools"
}
override var pinToContainer: Bool {
return true
true
}
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
@ -36,7 +34,7 @@ class ToolsPref: PrefPane, UiComponent {
source
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
.subscribe(onNext: { _ in
self.updateViews()
})
@ -53,7 +51,8 @@ class ToolsPref: PrefPane, UiComponent {
private let previewCheckbox = NSButton(forAutoLayout: ())
private let htmlCheckbox = NSButton(forAutoLayout: ())
required init?(coder: NSCoder) {
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -69,24 +68,32 @@ class ToolsPref: PrefPane, UiComponent {
let fileBrowser = self.fileBrowserCheckbox
fileBrowser.target = self
self.configureCheckbox(button: fileBrowser,
title: "File Browser",
action: #selector(ToolsPref.fileBrowserAction(_:)))
self.configureCheckbox(
button: fileBrowser,
title: "File Browser",
action: #selector(ToolsPref.fileBrowserAction(_:))
)
let openedFilesList = self.openedFilesListCheckbox
openedFilesList.target = self
self.configureCheckbox(button: openedFilesList,
title: "Buffers",
action: #selector(ToolsPref.openedFilesListAction(_:)))
self.configureCheckbox(
button: openedFilesList,
title: "Buffers",
action: #selector(ToolsPref.openedFilesListAction(_:))
)
let preview = self.previewCheckbox
preview.target = self
self.configureCheckbox(button: preview,
title: "Markdown Preview",
action: #selector(ToolsPref.previewAction(_:)))
self.configureCheckbox(
button: preview,
title: "Markdown Preview",
action: #selector(ToolsPref.previewAction(_:))
)
let html = self.htmlCheckbox
html.target = self
self.configureCheckbox(button: html,
title: "HTML Preview",
action: #selector(ToolsPref.htmlPreviewAction(_:)))
self.configureCheckbox(
button: html,
title: "HTML Preview",
action: #selector(ToolsPref.htmlPreviewAction(_:))
)
let info = self.infoTextField(
markdown: "You can turn off tools you don't need. The effect takes place when new windows are opened."
@ -123,24 +130,24 @@ class ToolsPref: PrefPane, UiComponent {
}
// MARK: - Actions
extension ToolsPref {
@IBAction func fileBrowserAction(_ sender: Any?) {
extension ToolsPref {
@IBAction func fileBrowserAction(_: Any?) {
self.tools[.fileBrowser] = self.fileBrowserCheckbox.boolState
self.emit(.setActiveTools(self.tools))
}
@IBAction func openedFilesListAction(_ sender: Any?) {
@IBAction func openedFilesListAction(_: Any?) {
self.tools[.buffersList] = self.openedFilesListCheckbox.boolState
self.emit(.setActiveTools(self.tools))
}
@IBAction func previewAction(_ sender: Any?) {
@IBAction func previewAction(_: Any?) {
self.tools[.preview] = self.previewCheckbox.boolState
self.emit(.setActiveTools(self.tools))
}
@IBAction func htmlPreviewAction(_ sender: Any?) {
@IBAction func htmlPreviewAction(_: Any?) {
self.tools[.htmlPreview] = self.htmlCheckbox.boolState
self.emit(.setActiveTools(self.tools))
}

View File

@ -6,7 +6,6 @@
import Foundation
class ToolsPrefReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = ToolsPref.Action
@ -14,10 +13,8 @@ class ToolsPrefReducer: ReducerType {
var state = pair.state
switch pair.action {
case let .setActiveTools(tools):
state.mainWindowTemplate.activeTools = tools
}
return (state, pair.action, true)

View File

@ -7,24 +7,21 @@ import Foundation
import RxSwift
struct StateActionPair<S, A> {
var state: S
var action: A
var modified: Bool
}
protocol UuidTagged {
var uuid: UUID { get }
}
class UuidAction<A>: UuidTagged, CustomStringConvertible {
let uuid: UUID
let payload: A
var description: String {
return "UuidAction(uuid: \(uuid), payload: \(String(reflecting: payload)))"
"UuidAction(uuid: \(self.uuid), payload: \(String(reflecting: self.payload)))"
}
init(uuid: UUID, action: A) {
@ -34,12 +31,11 @@ class UuidAction<A>: UuidTagged, CustomStringConvertible {
}
class UuidState<S>: UuidTagged, CustomStringConvertible {
let uuid: UUID
let payload: S
var description: String {
return "UuidState(uuid: \(uuid), payload: \(String(reflecting: payload)))"
"UuidState(uuid: \(self.uuid), payload: \(String(reflecting: self.payload)))"
}
init(uuid: UUID, state: S) {
@ -49,27 +45,25 @@ class UuidState<S>: UuidTagged, CustomStringConvertible {
}
class Token: Hashable, CustomStringConvertible {
func hash(into hasher: inout Hasher) {
hasher.combine(ObjectIdentifier(self))
}
var description: String {
return ObjectIdentifier(self).debugDescription
ObjectIdentifier(self).debugDescription
}
static func == (left: Token, right: Token) -> Bool {
return left === right
left === right
}
}
class Marked<T>: CustomStringConvertible {
let mark: Token
let payload: T
var description: String {
return "Marked<\(mark) -> \(self.payload)>"
"Marked<\(mark) -> \(self.payload)>"
}
convenience init(_ payload: T) {
@ -82,21 +76,18 @@ class Marked<T>: CustomStringConvertible {
}
func hasDifferentMark(as other: Marked<T>) -> Bool {
return self.mark != other.mark
self.mark != other.mark
}
}
class UiComponentTemplate: UiComponent {
typealias StateType = State
struct State {
var someField: String
}
enum Action {
case doSth
}
@ -115,7 +106,7 @@ class UiComponentTemplate: UiComponent {
source
.observeOn(MainScheduler.instance)
.subscribe(
onNext: { state in
onNext: { _ in
Swift.print("Hello, \(self.someField)")
}
)

View File

@ -7,11 +7,9 @@ import Cocoa
import RxSwift
class UiRoot: UiComponent {
typealias StateType = AppState
enum Action {
case quit
}
@ -56,11 +54,9 @@ class UiRoot: UiComponent {
guard self.mainWindows.isEmpty else { return }
switch state.afterLastWindowAction {
case .doNothing: return
case .hide: NSApp.hide(self)
case .quit: self.emit(.quit)
}
})
.disposed(by: self.disposeBag)
@ -108,9 +104,11 @@ class UiRoot: UiComponent {
.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) {

View File

@ -6,7 +6,6 @@
import Foundation
class UiRootReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = UiRoot.Action
@ -16,17 +15,14 @@ class UiRootReducer: ReducerType {
var appState = tuple.state
switch tuple.action {
case .quit:
appState.quit = true
}
return (appState, tuple.action, true)
}
class MainWindowReducer: ReducerType {
typealias StateType = AppState
typealias ActionType = UuidAction<MainWindow.Action>
@ -35,7 +31,6 @@ class UiRootReducer: ReducerType {
let uuid = tuple.action.uuid
switch tuple.action.payload {
case let .becomeKey(isFullScreen):
appState.currentMainWindowUuid = uuid
@ -49,7 +44,7 @@ class UiRootReducer: ReducerType {
isFullScreen: isFullScreen
)
case let .frameChanged(to:frame):
case let .frameChanged(to: frame):
if appState.mainWindows[uuid]?.isTemporarySession == true {
break
}
@ -63,7 +58,7 @@ class UiRootReducer: ReducerType {
break
}
appState.mainWindowTemplate.orderedTools = tools.map { $0.0 }
appState.mainWindowTemplate.orderedTools = tools.map(\.0)
case let .toggleAllTools(value):
if appState.mainWindows[uuid]?.isTemporarySession == true {
@ -90,8 +85,8 @@ class UiRootReducer: ReducerType {
}
if appState.currentMainWindowUuid == uuid,
let mainWindowToClose = appState.mainWindows[uuid] {
let mainWindowToClose = appState.mainWindows[uuid]
{
appState.currentMainWindowUuid = nil
appState.mainWindowTemplate = self.mainWindowTemplate(
from: appState.mainWindowTemplate,
@ -107,7 +102,6 @@ class UiRootReducer: ReducerType {
default:
return tuple
}
return (appState, tuple.action, true)
@ -115,8 +109,8 @@ class UiRootReducer: ReducerType {
private func mainWindowTemplate(from old: MainWindow.State,
new: MainWindow.State,
isFullScreen: Bool) -> MainWindow.State {
isFullScreen: Bool) -> MainWindow.State
{
var result = old
if !isFullScreen {