mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-24 11:37:32 +03:00
Merge remote-tracking branch 'origin/develop' into update-neovim
This commit is contained in:
commit
07f50b6b08
1
Cartfile
1
Cartfile
@ -10,5 +10,6 @@ github "qvacua/RxNeovimApi" "develop"
|
||||
github "sindresorhus/github-markdown-css" == 2.10.0
|
||||
github "httpswift/swifter" == 1.4.2
|
||||
github "a2/MessagePack.swift" == 3.0.0
|
||||
github "elegantchaos/DictionaryCoding" == 1.0.3
|
||||
|
||||
github "Quick/Nimble" == 7.1.2
|
||||
|
@ -2,6 +2,7 @@ github "PureLayout/PureLayout" "v3.0.2"
|
||||
github "Quick/Nimble" "v7.1.2"
|
||||
github "ReactiveX/RxSwift" "4.2.0"
|
||||
github "a2/MessagePack.swift" "3.0.0"
|
||||
github "elegantchaos/DictionaryCoding" "1.0.3"
|
||||
github "eonil/FileSystemEvents" "1.0.0"
|
||||
github "httpswift/swifter" "1.4.2"
|
||||
github "qvacua/CocoaFontAwesome" "76cf6c4ef3088d84f78988183c56fc6abdc19f83"
|
||||
|
@ -470,7 +470,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 284;
|
||||
CURRENT_PROJECT_VERSION = 285;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@ -530,7 +530,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 284;
|
||||
CURRENT_PROJECT_VERSION = 285;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@ -557,7 +557,7 @@
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 284;
|
||||
DYLIB_CURRENT_VERSION = 285;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
|
||||
FRAMEWORK_VERSION = A;
|
||||
@ -579,7 +579,7 @@
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 284;
|
||||
DYLIB_CURRENT_VERSION = 285;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
|
||||
FRAMEWORK_VERSION = A;
|
||||
|
@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>SNAPSHOT-284</string>
|
||||
<string>SNAPSHOT-285</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>284</string>
|
||||
<string>285</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2017 Tae Won Ha. All rights reserved.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
@ -142,7 +142,7 @@ extension NvimView {
|
||||
|
||||
case .insert:
|
||||
return self.bridge
|
||||
.vimInput("<ESC>\"+pa")
|
||||
.vimInput("<ESC>\"+Pa")
|
||||
.andThen(Single.just(pasteModeSet))
|
||||
|
||||
case .normal, .visual:
|
||||
|
@ -7,13 +7,11 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1929B00BA624DA8DC75F7E02 /* SerializableStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA42AB6F1BF631B57399 /* SerializableStates.swift */; };
|
||||
1929B04CE8ECBD75CBBB0991 /* StringCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5D45C9792BBE76B8AFF /* StringCommonsTest.swift */; };
|
||||
1929B05B9D664052EC2D23EF /* FileOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BCE3E156C06EDF1F2806 /* FileOutlineView.swift */; };
|
||||
1929B08C6230B9C5AB72DAF1 /* Pref128ToCurrentConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5046239709E33516F5C /* Pref128ToCurrentConverter.swift */; };
|
||||
1929B0E0C3BC59F52713D5A2 /* FoundationCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */; };
|
||||
1929B0F599D1F62C7BE53D2C /* HttpServerMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1DC584C89C477E83FA2 /* HttpServerMiddleware.swift */; };
|
||||
1929B10EE7FE8DC251B741B2 /* RxRedux.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B66A5E2D00EA143AFD86 /* RxRedux.swift */; };
|
||||
1929B1837C750CADB3A5BCB9 /* OpenQuicklyFileViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */; };
|
||||
1929B20CE35B43BB1CE023BA /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BC2F05E9A5C0DB039739 /* Theme.swift */; };
|
||||
1929B29B95AD176D57942E08 /* UiRootReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B457B9D0FA4D21F3751E /* UiRootReducer.swift */; };
|
||||
@ -81,6 +79,10 @@
|
||||
1929BF4FF30D9A9DE82C3052 /* FileUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B8042AC566CDF6C998A3 /* FileUtilsTest.swift */; };
|
||||
1929BFC70581084B5CE04A5B /* MatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BFE179BCA3C75A13D71B /* MatcherTests.swift */; };
|
||||
1929BFDE22D155F7C4B19E96 /* HtmlPreviewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B85023B042C485409CE1 /* HtmlPreviewTool.swift */; };
|
||||
4B004BAA20FBA6700043A396 /* DictionaryCoding.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B004BA920FBA6700043A396 /* DictionaryCoding.framework */; };
|
||||
4B004BAB20FBA6700043A396 /* DictionaryCoding.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B004BA920FBA6700043A396 /* DictionaryCoding.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4B004BAC20FBB4F10043A396 /* DictionaryCoding.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B004BA920FBA6700043A396 /* DictionaryCoding.framework */; };
|
||||
4B004BAD20FBBE1E0043A396 /* DictionaryCoding.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B004BA920FBA6700043A396 /* DictionaryCoding.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4B029F1A1D45E349004EE0D3 /* PrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B029F1C1D45E349004EE0D3 /* PrefWindow.xib */; };
|
||||
4B17E54D209E3EA400265C1D /* RxNeovimApi.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B17E54C209E3EA400265C1D /* RxNeovimApi.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4B17E54E209E3EFA00265C1D /* RxNeovimApi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B17E54C209E3EA400265C1D /* RxNeovimApi.framework */; };
|
||||
@ -234,6 +236,7 @@
|
||||
files = (
|
||||
4BB1F5D22097706700EC394A /* MessagePack.framework in Embed Frameworks */,
|
||||
4BB1F5CF2097704D00EC394A /* RxMsgpackRpc.framework in Embed Frameworks */,
|
||||
4B004BAB20FBA6700043A396 /* DictionaryCoding.framework in Embed Frameworks */,
|
||||
4BF18C411FD2E2C900DF95D1 /* CocoaFontAwesome.framework in Embed Frameworks */,
|
||||
4BF18C421FD2E2C900DF95D1 /* CocoaMarkdown.framework in Embed Frameworks */,
|
||||
4BF18C431FD2E2C900DF95D1 /* EonilFileSystemEvents.framework in Embed Frameworks */,
|
||||
@ -255,6 +258,7 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
4B004BAD20FBBE1E0043A396 /* DictionaryCoding.framework in CopyFiles */,
|
||||
4B9DF28A209C8DBB00DF2AAD /* RxMessagePort.framework in CopyFiles */,
|
||||
4B9DF289209C8DAD00DF2AAD /* RxMsgpackRpc.framework in CopyFiles */,
|
||||
4B17E54F209E3EFD00265C1D /* RxNeovimApi.framework in CopyFiles */,
|
||||
@ -313,7 +317,6 @@
|
||||
1929B9355C892BEBA7496C71 /* DictionaryCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryCommonsTest.swift; sourceTree = "<group>"; };
|
||||
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationCommons.swift; sourceTree = "<group>"; };
|
||||
1929B9D510177918080BE39B /* Scorer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scorer.swift; sourceTree = "<group>"; };
|
||||
1929BA42AB6F1BF631B57399 /* SerializableStates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerializableStates.swift; sourceTree = "<group>"; };
|
||||
1929BA43449BA41666CD55ED /* BufferList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferList.swift; sourceTree = "<group>"; };
|
||||
1929BA5C7099CDEB04B76BA4 /* FileBrowser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileBrowser.swift; sourceTree = "<group>"; };
|
||||
1929BA8AC40B901B20F20B71 /* FileUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
|
||||
@ -342,6 +345,7 @@
|
||||
1929BFB0F294F3714D5E095F /* PreviewToolReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewToolReducer.swift; sourceTree = "<group>"; };
|
||||
1929BFC0A5A9C6DB09BE1368 /* Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; };
|
||||
1929BFE179BCA3C75A13D71B /* MatcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherTests.swift; sourceTree = "<group>"; };
|
||||
4B004BA920FBA6700043A396 /* DictionaryCoding.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DictionaryCoding.framework; path = ../Carthage/Build/Mac/DictionaryCoding.framework; sourceTree = "<group>"; };
|
||||
4B029F1B1D45E349004EE0D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PrefWindow.xib; sourceTree = "<group>"; };
|
||||
4B17E54C209E3EA400265C1D /* RxNeovimApi.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxNeovimApi.framework; path = ../Carthage/Build/Mac/RxNeovimApi.framework; sourceTree = "<group>"; };
|
||||
4B19BEFA1E110183007E823C /* markdown */ = {isa = PBXFileReference; lastKnownFileType = folder; path = markdown; sourceTree = "<group>"; };
|
||||
@ -455,6 +459,7 @@
|
||||
files = (
|
||||
4BB1F5D12097705E00EC394A /* MessagePack.framework in Frameworks */,
|
||||
4BB1F5CD20976F8900EC394A /* RxMsgpackRpc.framework in Frameworks */,
|
||||
4B004BAA20FBA6700043A396 /* DictionaryCoding.framework in Frameworks */,
|
||||
4BF18C391FD2E2AB00DF95D1 /* EonilFileSystemEvents.framework in Frameworks */,
|
||||
4BF18C3A1FD2E2AB00DF95D1 /* PureLayout.framework in Frameworks */,
|
||||
4BF18C3B1FD2E2AB00DF95D1 /* CocoaMarkdown.framework in Frameworks */,
|
||||
@ -474,6 +479,7 @@
|
||||
files = (
|
||||
4BF18C581FD2E53400DF95D1 /* CocoaMarkdown.framework in Frameworks */,
|
||||
4BF18C511FD2E4F200DF95D1 /* RxTest.framework in Frameworks */,
|
||||
4B004BAC20FBB4F10043A396 /* DictionaryCoding.framework in Frameworks */,
|
||||
4BF18C4F1FD2E4F100DF95D1 /* RxSwift.framework in Frameworks */,
|
||||
4B17E54E209E3EFA00265C1D /* RxNeovimApi.framework in Frameworks */,
|
||||
4BF18C4C1FD2E4CE00DF95D1 /* NvimView.framework in Frameworks */,
|
||||
@ -570,7 +576,6 @@
|
||||
1929B5E773BDB3B4EE9D00C1 /* Reducers */,
|
||||
1929BFA93DC859DD76C46192 /* Middlewares */,
|
||||
1929BFC0A5A9C6DB09BE1368 /* Types.swift */,
|
||||
1929BA42AB6F1BF631B57399 /* SerializableStates.swift */,
|
||||
);
|
||||
name = UI;
|
||||
sourceTree = "<group>";
|
||||
@ -637,6 +642,7 @@
|
||||
4B5012001EBA791000F76C46 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B004BA920FBA6700043A396 /* DictionaryCoding.framework */,
|
||||
4B17E54C209E3EA400265C1D /* RxNeovimApi.framework */,
|
||||
4B9E5E1D20990E08006455C3 /* RxMessagePort.framework */,
|
||||
4BB1F5D02097705E00EC394A /* MessagePack.framework */,
|
||||
@ -1083,7 +1089,6 @@
|
||||
1929B4F0612224E594E89B92 /* AppearancePref.swift in Sources */,
|
||||
1929B50D933A369A86A165DE /* AdvencedPref.swift in Sources */,
|
||||
1929BCC7908DD899999B70BE /* AppearancePrefReducer.swift in Sources */,
|
||||
1929B00BA624DA8DC75F7E02 /* SerializableStates.swift in Sources */,
|
||||
1929B3557317755A43513B17 /* OpenQuicklyWindow.swift in Sources */,
|
||||
1929B333855A5406C400DA92 /* OpenQuicklyFilterOperation.swift in Sources */,
|
||||
1929B1837C750CADB3A5BCB9 /* OpenQuicklyFileViewRow.swift in Sources */,
|
||||
@ -1135,7 +1140,6 @@
|
||||
1929B8E90A1378E494D481E7 /* PrefUtilsTest.swift in Sources */,
|
||||
1929B20CE35B43BB1CE023BA /* Theme.swift in Sources */,
|
||||
1929B9318D32146D58BB38EC /* AppKitCommons.swift in Sources */,
|
||||
1929B10EE7FE8DC251B741B2 /* RxRedux.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1230,7 +1234,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 284;
|
||||
CURRENT_PROJECT_VERSION = 285;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@ -1287,7 +1291,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 284;
|
||||
CURRENT_PROJECT_VERSION = 285;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
|
@ -8,6 +8,7 @@ import RxSwift
|
||||
import PureLayout
|
||||
import Sparkle
|
||||
import CocoaFontAwesome
|
||||
import DictionaryCoding
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
|
||||
@ -35,8 +36,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
||||
let baseServerUrl = URL(string: "http://localhost:\(NetUtils.openPort())")!
|
||||
|
||||
var initialAppState: AppState
|
||||
if let stateDict = UserDefaults.standard.value(forKey: PrefMiddleware.compatibleVersion) as? [String: Any] {
|
||||
initialAppState = AppState(dict: stateDict) ?? .default
|
||||
|
||||
let dictDecoder = DictionaryDecoder()
|
||||
if let stateDict = UserDefaults.standard.value(forKey: PrefMiddleware.compatibleVersion) as? [String: Any],
|
||||
let state = try? dictDecoder.decode(AppState.self, from: stateDict) {
|
||||
|
||||
initialAppState = state
|
||||
} else {
|
||||
if let oldDict = UserDefaults.standard.value(forKey: PrefMiddleware.lastCompatibleVersion) as? [String: Any] {
|
||||
initialAppState = Pref128ToCurrentConverter.appState(from: oldDict)
|
||||
@ -44,6 +49,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
||||
initialAppState = .default
|
||||
}
|
||||
}
|
||||
|
||||
initialAppState.mainWindowTemplate.htmlPreview.server = Marked(
|
||||
baseServerUrl.appendingPathComponent(HtmlPreviewToolReducer.selectFirstPath)
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf400
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
@ -99,6 +99,11 @@ By:
|
||||
\b0 \
|
||||
\
|
||||
|
||||
\b DictionaryCoding
|
||||
\b0 \
|
||||
{\field{\*\fldinst{HYPERLINK "https://github.com/elegantchaos/DictionaryCoding"}}{\fldrslt https://github.com/elegantchaos/DictionaryCoding}}\
|
||||
\
|
||||
|
||||
\b Nimble
|
||||
\b0 \
|
||||
{\field{\*\fldinst{HYPERLINK "https://github.com/Quick/Nimble"}}{\fldrslt https://github.com/Quick/Nimble}}\
|
||||
|
@ -86,7 +86,6 @@ class Context: ReduxContext {
|
||||
httpMiddleware.mainWindow.apply,
|
||||
previewMiddleware.previewTool.apply,
|
||||
httpMiddleware.htmlPreview.apply,
|
||||
previewMiddleware.buffersList.apply,
|
||||
]
|
||||
)
|
||||
.filter { $0.modified }
|
||||
|
@ -49,7 +49,7 @@ class HttpServerMiddleware {
|
||||
return { tuple in
|
||||
let result = reduce(tuple)
|
||||
|
||||
guard tuple.modified else {
|
||||
guard case .selectHtmlFile = tuple.action.payload else {
|
||||
return result
|
||||
}
|
||||
|
||||
@ -58,6 +58,7 @@ class HttpServerMiddleware {
|
||||
return result
|
||||
}
|
||||
|
||||
fileLog.debug("Serving \(htmlFileUrl) on \(serverUrl)")
|
||||
let basePath = serverUrl.payload.deletingLastPathComponent().path
|
||||
|
||||
self.server.GET[serverUrl.payload.path] = shareFile(htmlFileUrl.path)
|
||||
@ -85,10 +86,6 @@ class HttpServerMiddleware {
|
||||
return { tuple in
|
||||
let result = reduce(tuple)
|
||||
|
||||
guard tuple.modified else {
|
||||
return result
|
||||
}
|
||||
|
||||
let uuidAction = tuple.action
|
||||
guard case .newCurrentBuffer = uuidAction.payload else {
|
||||
return result
|
||||
@ -104,7 +101,6 @@ class HttpServerMiddleware {
|
||||
}
|
||||
|
||||
fileLog.debug("Serving \(html) on \(server)")
|
||||
|
||||
let htmlBasePath = server.deletingLastPathComponent().path
|
||||
|
||||
self.server["\(htmlBasePath)/:path"] = shareFilesFromDirectory(buffer.deletingLastPathComponent().path)
|
||||
|
@ -1224,7 +1224,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>SNAPSHOT-284</string>
|
||||
<string>SNAPSHOT-285</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
@ -1241,7 +1241,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>284</string>
|
||||
<string>285</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.productivity</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
@ -52,7 +52,7 @@ class MainWindow: NSObject,
|
||||
case preview
|
||||
}
|
||||
|
||||
enum Tools: String {
|
||||
enum Tools: String, Codable {
|
||||
|
||||
static let all = Set([Tools.fileBrowser, Tools.buffersList, Tools.preview, Tools.htmlPreview])
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import DictionaryCoding
|
||||
|
||||
class PrefMiddleware: MiddlewareType {
|
||||
|
||||
@ -17,7 +18,12 @@ class PrefMiddleware: MiddlewareType {
|
||||
|
||||
// The following should only be used when Cmd-Q'ing
|
||||
func applyPref(from appState: AppState) {
|
||||
defaults.setValue(appState.dict(), forKey: PrefMiddleware.compatibleVersion)
|
||||
do {
|
||||
let dictionary: [String: Any] = try dictEncoder.encode(appState)
|
||||
defaults.set(dictionary, forKey: PrefMiddleware.compatibleVersion)
|
||||
} catch {
|
||||
fileLog.error("AppState could not converted to Dictionary: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
|
||||
@ -28,7 +34,12 @@ class PrefMiddleware: MiddlewareType {
|
||||
return result
|
||||
}
|
||||
|
||||
defaults.setValue(result.state.dict(), forKey: PrefMiddleware.compatibleVersion)
|
||||
do {
|
||||
let dictionary: [String: Any] = try dictEncoder.encode(result.state)
|
||||
defaults.set(dictionary, forKey: PrefMiddleware.compatibleVersion)
|
||||
} catch {
|
||||
fileLog.error("AppState could not converted to Dictionary: \(error)")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@ -52,7 +63,13 @@ class PrefMiddleware: MiddlewareType {
|
||||
return result
|
||||
}
|
||||
|
||||
defaults.setValue(result.state.dict(), forKey: PrefMiddleware.compatibleVersion)
|
||||
do {
|
||||
let dictionary: [String: Any] = try dictEncoder.encode(result.state)
|
||||
defaults.set(dictionary, forKey: PrefMiddleware.compatibleVersion)
|
||||
} catch {
|
||||
fileLog.error("AppState could not converted to Dictionary: \(error)")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@ -60,3 +77,4 @@ class PrefMiddleware: MiddlewareType {
|
||||
}
|
||||
|
||||
private let defaults = UserDefaults.standard
|
||||
private let dictEncoder = DictionaryEncoder()
|
||||
|
@ -9,13 +9,11 @@ import CocoaMarkdown
|
||||
class PreviewMiddleware {
|
||||
|
||||
let previewTool: PreviewToolMiddleware
|
||||
let buffersList: BuffersListMiddleware
|
||||
let mainWindow: MainWindowMiddleware
|
||||
|
||||
init() {
|
||||
let generator = PreviewGenerator()
|
||||
self.previewTool = PreviewToolMiddleware(generator: generator)
|
||||
self.buffersList = BuffersListMiddleware(generator: generator)
|
||||
self.mainWindow = MainWindowMiddleware(generator: generator)
|
||||
}
|
||||
|
||||
@ -49,7 +47,7 @@ class PreviewMiddleware {
|
||||
return
|
||||
}
|
||||
|
||||
fileLog.debug("\(buffer) -> \(html)")
|
||||
stdoutLog.debug("\(buffer) -> \(html)")
|
||||
do {
|
||||
try self.render(buffer, to: html)
|
||||
self.previewFiles[uuid] = html
|
||||
@ -98,10 +96,6 @@ class PreviewMiddleware {
|
||||
return { tuple in
|
||||
let result = reduce(tuple)
|
||||
|
||||
guard tuple.modified else {
|
||||
return result
|
||||
}
|
||||
|
||||
let uuidAction = tuple.action
|
||||
guard case .refreshNow = uuidAction.payload else {
|
||||
return result
|
||||
@ -115,37 +109,6 @@ class PreviewMiddleware {
|
||||
private let generator: PreviewGenerator
|
||||
}
|
||||
|
||||
class BuffersListMiddleware: MiddlewareType {
|
||||
|
||||
typealias StateType = MainWindow.State
|
||||
typealias ActionType = UuidAction<BuffersList.Action>
|
||||
|
||||
init(generator: PreviewGenerator) {
|
||||
self.generator = generator
|
||||
}
|
||||
|
||||
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
|
||||
return { tuple in
|
||||
let result = reduce(tuple)
|
||||
|
||||
guard tuple.modified else {
|
||||
return result
|
||||
}
|
||||
|
||||
let uuidAction = tuple.action
|
||||
guard case .open = uuidAction.payload else {
|
||||
return result
|
||||
}
|
||||
|
||||
self.generator.apply(result.state, uuid: uuidAction.uuid)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private let generator: PreviewGenerator
|
||||
}
|
||||
|
||||
class MainWindowMiddleware: MiddlewareType {
|
||||
|
||||
typealias StateType = MainWindow.State
|
||||
@ -159,10 +122,6 @@ class PreviewMiddleware {
|
||||
return { tuple in
|
||||
let result = reduce(tuple)
|
||||
|
||||
guard tuple.modified else {
|
||||
return result
|
||||
}
|
||||
|
||||
let uuidAction = tuple.action
|
||||
switch uuidAction.payload {
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
import Cocoa
|
||||
import RxSwift
|
||||
|
||||
extension Observable {
|
||||
extension ObservableType {
|
||||
|
||||
func mapOmittingNil<R>(_ transform: @escaping (E) throws -> R?) -> RxSwift.Observable<R> {
|
||||
return self
|
||||
|
@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol SerializableState {
|
||||
|
||||
init?(dict: [String: Any])
|
||||
|
||||
func dict() -> [String: Any]
|
||||
}
|
||||
|
||||
class Keys {
|
||||
|
||||
static let openNewOnLaunch = "open-new-window-when-launching"
|
||||
static let openNewOnReactivation = "open-new-window-on-reactivation"
|
||||
static let afterLastWindowAction = "after-last-window-action"
|
||||
static let useSnapshotUpdateChannel = "use-snapshot-update-channel"
|
||||
|
||||
class OpenQuickly {
|
||||
|
||||
static let key = "open-quickly"
|
||||
|
||||
static let ignorePatterns = "ignore-patterns"
|
||||
}
|
||||
|
||||
class Appearance {
|
||||
|
||||
static let key = "appearance"
|
||||
|
||||
static let usesTheme = "uses-theme"
|
||||
static let showsFileIcon = "shows-file-icon"
|
||||
static let editorFontName = "editor-font-name"
|
||||
static let editorFontSize = "editor-font-size"
|
||||
static let editorLinespacing = "editor-linespacing"
|
||||
static let editorUsesLigatures = "editor-uses-ligatures"
|
||||
}
|
||||
|
||||
class MainWindow {
|
||||
|
||||
static let key = "main-window"
|
||||
|
||||
static let allToolsVisible = "is-all-tools-visible"
|
||||
static let toolButtonsVisible = "is-tool-buttons-visible"
|
||||
static let orderedTools = "ordered-tools"
|
||||
static let activeTools = "active-tools"
|
||||
static let frame = "frame"
|
||||
|
||||
static let isLeftOptionMeta = "is-left-option-meta"
|
||||
static let isRightOptionMeta = "is-right-option-meta"
|
||||
|
||||
static let trackpadScrollResistance = "trackpad-scroll-resistance"
|
||||
static let useInteractiveZsh = "use-interactive-zsh"
|
||||
static let useLiveResize = "use-live-resize"
|
||||
static let isShowHidden = "is-show-hidden"
|
||||
}
|
||||
|
||||
class PreviewTool {
|
||||
|
||||
static let key = "preview-tool"
|
||||
|
||||
static let forwardSearchAutomatically = "is-forward-search-automatically"
|
||||
static let reverseSearchAutomatically = "is-reverse-search-automatically"
|
||||
static let refreshOnWrite = "is-refresh-on-write"
|
||||
}
|
||||
|
||||
class WorkspaceTool {
|
||||
|
||||
static let key = "workspace-tool"
|
||||
|
||||
static let location = "location"
|
||||
static let open = "is-visible"
|
||||
static let dimension = "dimension"
|
||||
}
|
||||
}
|
@ -6,9 +6,9 @@
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
struct AppState: SerializableState {
|
||||
struct AppState: Codable {
|
||||
|
||||
enum AfterLastWindowAction: String {
|
||||
enum AfterLastWindowAction: String, Codable {
|
||||
|
||||
case doNothing = "do-nothing"
|
||||
case hide = "hide"
|
||||
@ -17,6 +17,17 @@ struct AppState: SerializableState {
|
||||
|
||||
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"
|
||||
case useSnapshotUpdate = "use-snapshot-update-channel"
|
||||
|
||||
case openQuickly = "open-quickly"
|
||||
case mainWindowTemplate = "main-window"
|
||||
}
|
||||
|
||||
var openNewMainWindowOnLaunch = true
|
||||
var openNewMainWindowOnReactivation = true
|
||||
|
||||
@ -35,79 +46,64 @@ struct AppState: SerializableState {
|
||||
|
||||
var quit = false
|
||||
|
||||
init() {
|
||||
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.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)
|
||||
}
|
||||
|
||||
init?(dict: [String: Any]) {
|
||||
guard let openOnLaunch = PrefUtils.bool(from: dict, for: Keys.openNewOnLaunch),
|
||||
let openOnReactivation = PrefUtils.bool(from: dict, for: Keys.openNewOnReactivation),
|
||||
let useSnapshot = PrefUtils.bool(from: dict, for: Keys.useSnapshotUpdateChannel)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
// Use generated encode(to:)
|
||||
|
||||
self.openNewMainWindowOnLaunch = openOnLaunch
|
||||
self.openNewMainWindowOnReactivation = openOnReactivation
|
||||
|
||||
let lastWindowActionString = PrefUtils.string(from: dict, for: Keys.afterLastWindowAction)
|
||||
?? AfterLastWindowAction.doNothing.rawValue
|
||||
self.afterLastWindowAction = AfterLastWindowAction(rawValue: lastWindowActionString) ?? .doNothing
|
||||
|
||||
self.useSnapshotUpdate = useSnapshot
|
||||
|
||||
let openQuicklyDict = dict[Keys.OpenQuickly.key] as? [String: Any] ?? [:]
|
||||
self.openQuickly = OpenQuicklyWindow.State(dict: openQuicklyDict) ?? OpenQuicklyWindow.State.default
|
||||
|
||||
let mainWindowDict = dict[Keys.MainWindow.key] as? [String: Any] ?? [:]
|
||||
self.mainWindowTemplate = MainWindow.State(dict: mainWindowDict) ?? MainWindow.State.default
|
||||
}
|
||||
|
||||
func dict() -> [String: Any] {
|
||||
return [
|
||||
Keys.openNewOnLaunch: self.openNewMainWindowOnLaunch,
|
||||
Keys.openNewOnReactivation: self.openNewMainWindowOnReactivation,
|
||||
Keys.afterLastWindowAction: self.afterLastWindowAction.rawValue,
|
||||
Keys.useSnapshotUpdateChannel: self.useSnapshotUpdate,
|
||||
|
||||
Keys.OpenQuickly.key: self.openQuickly.dict(),
|
||||
|
||||
Keys.MainWindow.key: self.mainWindowTemplate.dict(),
|
||||
]
|
||||
private init() {
|
||||
}
|
||||
}
|
||||
|
||||
extension OpenQuicklyWindow {
|
||||
|
||||
struct State: SerializableState {
|
||||
struct State: Codable {
|
||||
|
||||
static let `default` = State()
|
||||
static let defaultIgnorePatterns = Set(["*/.git", "*.o", "*.d", "*.dia"].map(FileItemIgnorePattern.init))
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
|
||||
case ignorePatterns = "ignore-patterns"
|
||||
}
|
||||
|
||||
let root = FileItem(URL(fileURLWithPath: "/", isDirectory: true))
|
||||
|
||||
var flatFileItems = Observable<[FileItem]>.empty()
|
||||
var cwd = FileUtils.userHomeUrl
|
||||
var ignorePatterns = Set(["*/.git", "*.o", "*.d", "*.dia"].map(FileItemIgnorePattern.init))
|
||||
var ignorePatterns = State.defaultIgnorePatterns
|
||||
var ignoreToken = Token()
|
||||
|
||||
var open = false
|
||||
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
init?(dict: [String: Any]) {
|
||||
guard let patternsString = PrefUtils.string(from: dict, for: Keys.OpenQuickly.ignorePatterns) else {
|
||||
return nil
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
if let patternsAsString = try container.decodeIfPresent(String.self, forKey: .ignorePatterns) {
|
||||
self.ignorePatterns = FileItemIgnorePattern.from(string: patternsAsString)
|
||||
} else {
|
||||
self.ignorePatterns = State.defaultIgnorePatterns
|
||||
}
|
||||
|
||||
self.ignorePatterns = FileItemIgnorePattern.from(string: patternsString)
|
||||
}
|
||||
|
||||
func dict() -> [String: Any] {
|
||||
return [
|
||||
Keys.OpenQuickly.ignorePatterns: FileItemIgnorePattern.toString(self.ignorePatterns)
|
||||
]
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(FileItemIgnorePattern.toString(self.ignorePatterns), forKey: .ignorePatterns)
|
||||
}
|
||||
|
||||
private init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,10 +166,20 @@ struct HtmlPreviewState {
|
||||
var server: Marked<URL>?
|
||||
}
|
||||
|
||||
struct AppearanceState: SerializableState {
|
||||
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"
|
||||
case editorFontSize = "editor-font-size"
|
||||
case editorLinespacing = "editor-linespacing"
|
||||
case editorUsesLigatures = "editor-uses-ligatures"
|
||||
}
|
||||
|
||||
var font = NSFont.userFixedPitchFont(ofSize: 13)!
|
||||
var linespacing: CGFloat = 1
|
||||
var usesLigatures = false
|
||||
@ -182,45 +188,54 @@ struct AppearanceState: SerializableState {
|
||||
var showsFileIcon = true
|
||||
var theme = Marked(Theme.default)
|
||||
|
||||
init() {
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
}
|
||||
|
||||
init?(dict: [String: Any]) {
|
||||
guard let editorFontName = dict[Keys.Appearance.editorFontName] as? String,
|
||||
let fEditorFontSize = PrefUtils.float(from: dict, for: Keys.Appearance.editorFontSize),
|
||||
let fEditorLinespacing = PrefUtils.float(from: dict, for: Keys.Appearance.editorLinespacing),
|
||||
let editorUsesLigatures = PrefUtils.bool(from: dict, for: Keys.Appearance.editorUsesLigatures)
|
||||
else {
|
||||
return nil
|
||||
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: CGFloat(fontSize)) {
|
||||
self.font = font
|
||||
} else {
|
||||
self.font = NvimView.defaultFont
|
||||
}
|
||||
|
||||
self.usesTheme = PrefUtils.bool(from: dict, for: Keys.Appearance.usesTheme, default: true)
|
||||
self.showsFileIcon = PrefUtils.bool(from: dict, for: Keys.Appearance.showsFileIcon, default: true)
|
||||
self.linespacing = CGFloat(try container.decodeIfPresent(Float.self, forKey: .editorLinespacing) ?? 1.0)
|
||||
self.usesLigatures = try container.decodeIfPresent(Bool.self, forKey: .editorUsesLigatures) ?? true
|
||||
|
||||
self.font = PrefUtils.saneFont(editorFontName, fontSize: CGFloat(fEditorFontSize))
|
||||
self.linespacing = CGFloat(fEditorLinespacing)
|
||||
self.usesLigatures = editorUsesLigatures
|
||||
self.usesTheme = try container.decodeIfPresent(Bool.self, forKey: .usesTheme) ?? true
|
||||
self.showsFileIcon = try container.decodeIfPresent(Bool.self, forKey: .showsFileIcon) ?? true
|
||||
}
|
||||
|
||||
func dict() -> [String: Any] {
|
||||
return [
|
||||
Keys.Appearance.usesTheme: self.usesTheme,
|
||||
Keys.Appearance.showsFileIcon: self.showsFileIcon,
|
||||
Keys.Appearance.editorFontName: self.font.fontName,
|
||||
Keys.Appearance.editorFontSize: Float(self.font.pointSize),
|
||||
Keys.Appearance.editorLinespacing: Float(self.linespacing),
|
||||
Keys.Appearance.editorUsesLigatures: self.usesLigatures,
|
||||
]
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encode(self.usesTheme, forKey: .usesTheme)
|
||||
try container.encode(self.showsFileIcon, forKey: .showsFileIcon)
|
||||
try container.encode(self.font.fontName, forKey: .editorFontName)
|
||||
try container.encode(self.font.pointSize, forKey: .editorFontSize)
|
||||
try container.encode(self.linespacing, forKey: .editorLinespacing)
|
||||
try container.encode(self.usesLigatures, forKey: .editorUsesLigatures)
|
||||
}
|
||||
|
||||
private init() {
|
||||
}
|
||||
}
|
||||
|
||||
extension MainWindow {
|
||||
|
||||
struct State: SerializableState {
|
||||
struct State: Codable {
|
||||
|
||||
static let `default` = State(isAllToolsVisible: true, isToolButtonsVisible: true)
|
||||
|
||||
static let defaultTools: [MainWindow.Tools: WorkspaceToolState] = [
|
||||
.fileBrowser: WorkspaceToolState(location: .left, dimension: 200, open: true),
|
||||
.buffersList: WorkspaceToolState(location: .left, dimension: 200, open: false),
|
||||
.preview: WorkspaceToolState(location: .right, dimension: 250, open: false),
|
||||
.htmlPreview: WorkspaceToolState(location: .right, dimension: 500, open: false),
|
||||
]
|
||||
|
||||
static let orderedDefault: [MainWindow.Tools] = [.fileBrowser, .buffersList, .preview, .htmlPreview]
|
||||
|
||||
var isAllToolsVisible = true
|
||||
var isToolButtonsVisible = true
|
||||
var activeTools = [
|
||||
@ -236,8 +251,8 @@ extension MainWindow {
|
||||
var goToLineFromCli: Marked<Int>?
|
||||
var lastFileSystemUpdate = Marked(FileUtils.userHomeUrl)
|
||||
|
||||
var tools = WorkspaceToolState.default
|
||||
var orderedTools = WorkspaceToolState.orderedDefault
|
||||
var tools = MainWindow.State.defaultTools
|
||||
var orderedTools = MainWindow.State.orderedDefault
|
||||
|
||||
var preview = PreviewState.default
|
||||
var htmlPreview = HtmlPreviewState.default
|
||||
@ -277,42 +292,57 @@ extension MainWindow {
|
||||
self.isToolButtonsVisible = isToolButtonsVisible
|
||||
}
|
||||
|
||||
init?(dict: [String: Any]) {
|
||||
guard let isAllToolsVisible = PrefUtils.bool(from: dict, for: Keys.MainWindow.allToolsVisible),
|
||||
let isToolButtonsVisible = PrefUtils.bool(from: dict, for: Keys.MainWindow.toolButtonsVisible),
|
||||
let orderedToolsAsString = dict[Keys.MainWindow.orderedTools] as? [String],
|
||||
let isShowHidden = PrefUtils.bool(from: dict, for: Keys.MainWindow.isShowHidden)
|
||||
else {
|
||||
return nil
|
||||
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 isLeftOptionMeta = "is-left-option-meta"
|
||||
case isRightOptionMeta = "is-right-option-meta"
|
||||
|
||||
case trackpadScrollResistance = "trackpad-scroll-resistance"
|
||||
case useInteractiveZsh = "use-interactive-zsh"
|
||||
case useLiveResize = "use-live-resize"
|
||||
case isShowHidden = "is-show-hidden"
|
||||
|
||||
case appearance = "appearance"
|
||||
case workspaceTools = "workspace-tool"
|
||||
case previewTool = "preview-tool"
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
}
|
||||
|
||||
// Stay compatible with 168
|
||||
self.isLeftOptionMeta = PrefUtils.bool(from: dict, for: Keys.MainWindow.isLeftOptionMeta, default: false)
|
||||
self.isRightOptionMeta = PrefUtils.bool(from: dict, for: Keys.MainWindow.isRightOptionMeta, default: false)
|
||||
self.isAllToolsVisible = try container.decode(forKey: .allToolsVisible, default: State.default.isAllToolsVisible)
|
||||
self.isToolButtonsVisible = try container.decode(forKey: .toolButtonsVisible,
|
||||
default: State.default.isToolButtonsVisible)
|
||||
|
||||
self.useInteractiveZsh = PrefUtils.bool(from: dict, for: Keys.MainWindow.useInteractiveZsh, default: false)
|
||||
self.trackpadScrollResistance = PrefUtils.value(from: dict,
|
||||
for: Keys.MainWindow.trackpadScrollResistance,
|
||||
default: 5.0)
|
||||
self.useLiveResize = PrefUtils.bool(from: dict, for: Keys.MainWindow.useLiveResize, default: false)
|
||||
let frameString = PrefUtils.string(from: dict,
|
||||
for: Keys.MainWindow.frame,
|
||||
default: NSStringFromRect(self.frame))
|
||||
self.frame = NSRectFromString(frameString)
|
||||
self.appearance = try container.decode(forKey: .appearance, default: State.default.appearance)
|
||||
|
||||
self.isAllToolsVisible = isAllToolsVisible
|
||||
self.isToolButtonsVisible = isToolButtonsVisible
|
||||
|
||||
let appearanceDict = dict[Keys.Appearance.key] as? [String: Any] ?? [:]
|
||||
self.appearance = AppearanceState(dict: appearanceDict) ?? AppearanceState.default
|
||||
|
||||
self.orderedTools = orderedToolsAsString.compactMap { MainWindow.Tools(rawValue: $0) }
|
||||
self.orderedTools = try container.decode(forKey: .orderedTools, default: State.default.orderedTools)
|
||||
let missingOrderedTools = MainWindow.Tools.all.subtracting(self.orderedTools)
|
||||
self.orderedTools.append(contentsOf: missingOrderedTools)
|
||||
|
||||
// To stay compatible with 168 we do not guard against nil activeToolsAsString.
|
||||
let activeToolsAsString = dict[Keys.MainWindow.activeTools] as? [String: Bool] ?? [:]
|
||||
self.activeTools = activeToolsAsString.flatMapToDict { (key, value) in
|
||||
// See [1]
|
||||
let rawActiveTools: [String: Bool] = try container.decode(forKey: .activeTools, default: [:])
|
||||
self.activeTools = rawActiveTools.flatMapToDict { (key, value) in
|
||||
guard let toolId = MainWindow.Tools(rawValue: key) else {
|
||||
return nil
|
||||
}
|
||||
@ -322,138 +352,135 @@ extension MainWindow {
|
||||
let missingActiveTools = MainWindow.Tools.all.subtracting(self.activeTools.keys)
|
||||
missingActiveTools.forEach { self.activeTools[$0] = true }
|
||||
|
||||
let workspaceToolsDict = dict[Keys.WorkspaceTool.key] as? [String: [String: Any]] ?? [:]
|
||||
let toolKeys = workspaceToolsDict.keys.compactMap { MainWindow.Tools(rawValue: $0) }
|
||||
let missingToolKeys = MainWindow.Tools.all.subtracting(toolKeys)
|
||||
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
|
||||
}
|
||||
|
||||
var tools = Array(toolKeys).toDict { tool in
|
||||
return WorkspaceToolState(dict: workspaceToolsDict[tool.rawValue]!) ?? WorkspaceToolState.default[tool]!
|
||||
return (tool, value)
|
||||
}
|
||||
missingToolKeys.forEach { missingTool in
|
||||
tools[missingTool] = WorkspaceToolState.default[missingTool]!
|
||||
let missingTools = MainWindow.Tools.all.subtracting(self.tools.keys)
|
||||
missingTools.forEach { missingTool in
|
||||
self.tools[missingTool] = MainWindow.State.defaultTools[missingTool]!
|
||||
}
|
||||
|
||||
self.tools = tools
|
||||
|
||||
let previewToolDict = dict[Keys.PreviewTool.key] as? [String: Any] ?? [:]
|
||||
self.previewTool = PreviewTool.State(dict: previewToolDict) ?? PreviewTool.State.default
|
||||
|
||||
self.fileBrowserShowHidden = isShowHidden
|
||||
self.previewTool = try container.decode(forKey: .previewTool, default: State.default.previewTool)
|
||||
self.fileBrowserShowHidden = try container.decode(forKey: .isShowHidden,
|
||||
default: State.default.fileBrowserShowHidden)
|
||||
}
|
||||
|
||||
func dict() -> [String: Any] {
|
||||
return [
|
||||
Keys.MainWindow.allToolsVisible: self.isAllToolsVisible,
|
||||
Keys.MainWindow.toolButtonsVisible: self.isToolButtonsVisible,
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
Keys.MainWindow.frame: NSStringFromRect(self.frame),
|
||||
try container.encode(self.isAllToolsVisible, forKey: .allToolsVisible)
|
||||
try container.encode(self.isToolButtonsVisible, forKey: .toolButtonsVisible)
|
||||
try container.encode(NSStringFromRect(self.frame), forKey: .frame)
|
||||
try container.encode(self.trackpadScrollResistance, forKey: .trackpadScrollResistance)
|
||||
try container.encode(self.useLiveResize, forKey: .useLiveResize)
|
||||
try container.encode(self.isLeftOptionMeta, forKey: .isLeftOptionMeta)
|
||||
try container.encode(self.isRightOptionMeta, forKey: .isRightOptionMeta)
|
||||
try container.encode(self.useInteractiveZsh, forKey: .useInteractiveZsh)
|
||||
try container.encode(self.fileBrowserShowHidden, forKey: .isShowHidden)
|
||||
|
||||
Keys.MainWindow.trackpadScrollResistance: self.trackpadScrollResistance,
|
||||
Keys.MainWindow.useLiveResize: self.useLiveResize,
|
||||
// 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)
|
||||
|
||||
Keys.Appearance.key: self.appearance.dict(),
|
||||
Keys.WorkspaceTool.key: self.tools.mapToDict { ($0.rawValue, $1.dict()) },
|
||||
|
||||
Keys.MainWindow.isLeftOptionMeta: self.isLeftOptionMeta,
|
||||
Keys.MainWindow.isRightOptionMeta: self.isRightOptionMeta,
|
||||
|
||||
Keys.MainWindow.orderedTools: self.orderedTools.map { $0.rawValue },
|
||||
Keys.MainWindow.activeTools: self.activeTools.mapToDict { ($0.rawValue, $1) },
|
||||
|
||||
Keys.PreviewTool.key: self.previewTool.dict(),
|
||||
|
||||
Keys.MainWindow.isShowHidden: self.fileBrowserShowHidden,
|
||||
Keys.MainWindow.useInteractiveZsh: self.useInteractiveZsh,
|
||||
]
|
||||
try container.encode(self.appearance, forKey: .appearance)
|
||||
try container.encode(self.orderedTools, forKey: .orderedTools)
|
||||
try container.encode(self.previewTool, forKey: .previewTool)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WorkspaceToolState: SerializableState {
|
||||
struct WorkspaceToolState: Codable {
|
||||
|
||||
static let `default` = [
|
||||
MainWindow.Tools.fileBrowser: WorkspaceToolState(location: .left, dimension: 200, open: true),
|
||||
MainWindow.Tools.buffersList: WorkspaceToolState(location: .left, dimension: 200, open: false),
|
||||
MainWindow.Tools.preview: WorkspaceToolState(location: .right, dimension: 250, open: false),
|
||||
MainWindow.Tools.htmlPreview: WorkspaceToolState(location: .right, dimension: 500, open: false),
|
||||
]
|
||||
static let `default` = WorkspaceToolState()
|
||||
|
||||
static let `orderedDefault` = [
|
||||
MainWindow.Tools.fileBrowser,
|
||||
MainWindow.Tools.buffersList,
|
||||
MainWindow.Tools.preview,
|
||||
MainWindow.Tools.htmlPreview,
|
||||
]
|
||||
enum CodingKeys: String, CodingKey {
|
||||
|
||||
case location = "location"
|
||||
case `open` = "is-visible"
|
||||
case dimension = "dimension"
|
||||
}
|
||||
|
||||
var location = WorkspaceBarLocation.left
|
||||
var dimension = CGFloat(200)
|
||||
var open = false
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
self.location = try container.decode(forKey: .location, default: WorkspaceToolState.default.location)
|
||||
self.dimension = CGFloat(try container.decode(forKey: .dimension, default: WorkspaceToolState.default.dimension))
|
||||
self.open = try container.decode(forKey: .open, default: WorkspaceToolState.default.open)
|
||||
}
|
||||
|
||||
// Use generated encode(to:)
|
||||
|
||||
private init() {
|
||||
}
|
||||
|
||||
init(location: WorkspaceBarLocation, dimension: CGFloat, open: Bool) {
|
||||
self.location = location
|
||||
self.dimension = dimension
|
||||
self.open = open
|
||||
}
|
||||
|
||||
init?(dict: [String: Any]) {
|
||||
guard let locationRawValue = dict[Keys.WorkspaceTool.location] as? String,
|
||||
let isOpen = PrefUtils.bool(from: dict, for: Keys.WorkspaceTool.open),
|
||||
let fDimension = PrefUtils.float(from: dict, for: Keys.WorkspaceTool.dimension)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let location = WorkspaceBarLocation(rawValue: locationRawValue) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.location = location
|
||||
self.dimension = CGFloat(fDimension)
|
||||
self.open = isOpen
|
||||
}
|
||||
|
||||
func dict() -> [String: Any] {
|
||||
return [
|
||||
Keys.WorkspaceTool.location: self.location.rawValue,
|
||||
Keys.WorkspaceTool.open: self.open,
|
||||
Keys.WorkspaceTool.dimension: Float(self.dimension),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
extension PreviewTool {
|
||||
|
||||
struct State: SerializableState {
|
||||
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"
|
||||
}
|
||||
|
||||
var isForwardSearchAutomatically = false
|
||||
var isReverseSearchAutomatically = false
|
||||
var isRefreshOnWrite = true
|
||||
|
||||
init() {
|
||||
|
||||
private init() {
|
||||
}
|
||||
|
||||
init?(dict: [String: Any]) {
|
||||
guard let isForward = PrefUtils.bool(from: dict, for: Keys.PreviewTool.forwardSearchAutomatically),
|
||||
let isReverse = PrefUtils.bool(from: dict, for: Keys.PreviewTool.reverseSearchAutomatically),
|
||||
let isRefreshOnWrite = PrefUtils.bool(from: dict, for: Keys.PreviewTool.refreshOnWrite)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
self.isRefreshOnWrite = isRefreshOnWrite
|
||||
self.isForwardSearchAutomatically = isForward
|
||||
self.isReverseSearchAutomatically = isReverse
|
||||
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 dict() -> [String: Any] {
|
||||
return [
|
||||
Keys.PreviewTool.forwardSearchAutomatically: self.isForwardSearchAutomatically,
|
||||
Keys.PreviewTool.reverseSearchAutomatically: self.isReverseSearchAutomatically,
|
||||
Keys.PreviewTool.refreshOnWrite: self.isRefreshOnWrite,
|
||||
]
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encode(self.isForwardSearchAutomatically, forKey: .forwardSearchAutomatically)
|
||||
try container.encode(self.isReverseSearchAutomatically, forKey: .reverseSearchAutomatically)
|
||||
try container.encode(self.isRefreshOnWrite, forKey: .refreshOnWrite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension KeyedDecodingContainer where K: CodingKey {
|
||||
|
||||
fileprivate func decode<T: Decodable>(forKey key: K, `default`: T) throws -> T {
|
||||
return try self.decodeIfPresent(T.self, forKey: key) ?? `default`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
[1] Swift 4.2 has a bug: Only when a `Dictionary` has `String` or `Int` keys, it is encoded to dictionary.
|
||||
This means that `Dictionary`s with `enum SomeEnum: String, Codable` keys are encoded as `Array`s.
|
||||
The same problem persists also for decoding.
|
||||
<https://forums.swift.org/t/json-encoding-decoding-weird-encoding-of-dictionary-with-enum-values/12995>
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@
|
||||
import Cocoa
|
||||
import PureLayout
|
||||
|
||||
enum WorkspaceBarLocation: String {
|
||||
enum WorkspaceBarLocation: String, Codable {
|
||||
|
||||
case top = "top"
|
||||
case right = "right"
|
||||
|
@ -15,10 +15,10 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>SNAPSHOT-284</string>
|
||||
<string>SNAPSHOT-285</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>284</string>
|
||||
<string>285</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -7,22 +7,22 @@
|
||||
<description>Most recent changes with links to updates for VimR.</description>
|
||||
<language>en</language>
|
||||
<item>
|
||||
<title>SNAPSHOT-284</title>
|
||||
<title>SNAPSHOT-285</title>
|
||||
<description><![CDATA[
|
||||
<ul>
|
||||
<li>GH-443: <code>vimr --line ${LINE_NUMBER} ${SOME_FILE}</code> will open the file and go to the given line. If the file is already open in a UI window, then that window will be selected and the cursor will be moved to the given line. This can be used e.g. to reverse-search LaTeX. Note that you have to re-install the <code>vimr</code> tool.</li>
|
||||
<li>GH-603: Bugfix: <code>Cmd-V</code> pastes at the wrong location in the insert mode.</li>
|
||||
</ul>
|
||||
]]></description>
|
||||
<releaseNotesLink>
|
||||
https://github.com/qvacua/vimr/releases/tag/snapshot/284
|
||||
https://github.com/qvacua/vimr/releases/tag/snapshot/285
|
||||
</releaseNotesLink>
|
||||
<pubDate>2018-07-06T21:01:36.974431</pubDate>
|
||||
<pubDate>2018-07-15T22:07:13.166982</pubDate>
|
||||
<minimumSystemVersion>10.10.0</minimumSystemVersion>
|
||||
<enclosure url="https://github.com/qvacua/vimr/releases/download/snapshot/284/VimR-SNAPSHOT-284.tar.bz2"
|
||||
sparkle:version="284"
|
||||
sparkle:shortVersionString="SNAPSHOT-284"
|
||||
sparkle:dsaSignature="MC4CFQC85W5DOK+chBghYPusLQGPdfrXWAIVAOKVRd3YSnGyXJ3w5S3F7LU4vJTM"
|
||||
length="14182159"
|
||||
<enclosure url="https://github.com/qvacua/vimr/releases/download/snapshot/285/VimR-SNAPSHOT-285.tar.bz2"
|
||||
sparkle:version="285"
|
||||
sparkle:shortVersionString="SNAPSHOT-285"
|
||||
sparkle:dsaSignature="MC0CFHyBjevzdZbw+AXyogsP2oPp4qCuAhUApBfhVtzcySv3hMPmKo0oaWTBDuo="
|
||||
length="14797431"
|
||||
type="application/octet-stream"/>
|
||||
</item>
|
||||
</channel>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
* GH-625: `vimr --cur-env` will pass the current environment variables to the new neovim process. This will result in `virtualenv` support.
|
||||
* GH-443: `vimr --line ${LINE_NUMBER} ${SOME_FILE}` will open the file and go to the given line. If the file is already open in a UI window, then that window will be selected and the cursor will be moved to the given line. This can be used e.g. to reverse-search LaTeX.
|
||||
* GH-603: Bugfix: `Cmd-V` pastes at the wrong location in the insert mode.
|
||||
* Dependencies updates:
|
||||
- ReactiveX/RxSwift@4.2.0
|
||||
- httpswift/swifter@1.4.2
|
||||
|
Loading…
Reference in New Issue
Block a user