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

Merge remote-tracking branch 'origin/develop' into update-neovim

Conflicts:
	NvimView/neovim
	RxPack/RxNeovimApi.generated.swift
This commit is contained in:
Tae Won Ha 2020-03-12 19:36:53 +01:00
commit fc7ce69ce4
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
68 changed files with 1521 additions and 1000 deletions

View File

@ -5,9 +5,13 @@
import Foundation
struct FontTrait: OptionSet {
public struct FontTrait: OptionSet {
let rawValue: UInt
public let rawValue: UInt
public init(rawValue: UInt) {
self.rawValue = rawValue
}
static let italic = FontTrait(rawValue: 1 << 0)
static let bold = FontTrait(rawValue: 1 << 1)

View File

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.32.0</string>
<string>SNAPSHOT-347</string>
<key>CFBundleVersion</key>
<string>344</string>
<string>347</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>

View File

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11134" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11134"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@ -10,8 +12,8 @@
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSApplication"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target">
<customObject id="-3" userLabel="Application"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="DrawerPerf" customModuleProvider="target">
<connections>
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
</connections>
@ -627,7 +629,7 @@
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="toggleSourceList:" target="-1" id="iwa-gc-5KM"/>
<action selector="toggleSidebar:" target="-1" id="iwa-gc-5KM"/>
</connections>
</menuItem>
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
@ -677,12 +679,13 @@
</menu>
</menuItem>
</items>
<point key="canvasLocation" x="-273" y="154"/>
</menu>
<window title="DrawerPerf" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1177"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>

View File

@ -5,9 +5,13 @@
import Foundation
struct FontTrait: OptionSet {
public struct FontTrait: OptionSet {
let rawValue: UInt
public let rawValue: UInt
public init(rawValue: UInt) {
self.rawValue = rawValue
}
static let italic = FontTrait(rawValue: 1 << 0)
static let bold = FontTrait(rawValue: 1 << 1)

View File

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.32.0</string>
<string>SNAPSHOT-347</string>
<key>CFBundleVersion</key>
<string>344</string>
<string>347</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11134" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11134"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@ -10,8 +11,8 @@
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSApplication"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="MinimalNvimViewDemo" customModuleProvider="target"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
@ -660,6 +661,24 @@
</items>
</menu>
</menuItem>
<menuItem title="Debug" id="skz-pX-70k">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Debug" id="wAk-gE-S2r">
<items>
<menuItem title="Item 1" keyEquivalent="1" id="Hhm-s9-0as">
<connections>
<action selector="debug1:" target="-1" id="PRC-9e-nH2"/>
</connections>
</menuItem>
<menuItem title="Item 2" id="ngm-jM-Skm">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Item 3" id="kEM-MW-m60">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
@ -673,6 +692,7 @@
</menu>
</menuItem>
</items>
<point key="canvasLocation" x="140" y="154"/>
</menu>
</objects>
</document>

View File

@ -29,7 +29,7 @@ class Document: NSDocument, NSWindowDelegate {
case .neoVimStopped: self.close()
default: break //Swift.print("Event received: \(event)")
default: break
}
})

View File

@ -38,9 +38,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.32.0</string>
<string>SNAPSHOT-347</string>
<key>CFBundleVersion</key>
<string>344</string>
<string>347</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>

View File

@ -47,7 +47,7 @@ static void server_ui_main(UIBridgeData *bridge, UI *ui);
#pragma mark ui_bridge callbacks
static void server_ui_flush(UI *ui __unused) {
if (flush_sbuffer.size == 0) { return; }
if (flush_sbuffer.size == 0) {return;}
CFDataRef const data = CFDataCreateWithBytesNoCopy(
kCFAllocatorDefault,
@ -145,10 +145,10 @@ static void server_ui_hl_attr_define(
Array info __unused
) {
FontTrait trait = FontTraitNone;
if (attrs.rgb_ae_attr & HL_ITALIC) { trait |= FontTraitItalic; }
if (attrs.rgb_ae_attr & HL_BOLD) { trait |= FontTraitBold; }
if (attrs.rgb_ae_attr & HL_UNDERLINE) { trait |= FontTraitUnderline; }
if (attrs.rgb_ae_attr & HL_UNDERCURL) { trait |= FontTraitUndercurl; }
if (attrs.rgb_ae_attr & HL_ITALIC) {trait |= FontTraitItalic;}
if (attrs.rgb_ae_attr & HL_BOLD) {trait |= FontTraitBold;}
if (attrs.rgb_ae_attr & HL_UNDERLINE) {trait |= FontTraitUnderline;}
if (attrs.rgb_ae_attr & HL_UNDERCURL) {trait |= FontTraitUndercurl;}
send_msg_packing(NvimServerMsgIdHighlightAttrs, ^(msgpack_packer *packer) {
msgpack_pack_array(packer, 6);
@ -161,6 +161,9 @@ static void server_ui_hl_attr_define(
});
}
static void server_hl_group_set(UI *ui, String name, Integer id) {
}
static void server_ui_raw_line(
UI *ui __unused,
Integer grid __unused,
@ -185,9 +188,9 @@ static void server_ui_raw_line(
msgpack_pack_int64(packer, clearattr);
msgpack_pack_array(packer, (size_t) count);
for (Integer i = 0; i < count; i++) { msgpack_pack_cstr(packer, (const char *) chunk[i]); }
for (Integer i = 0; i < count; i++) {msgpack_pack_cstr(packer, (const char *) chunk[i]);}
msgpack_pack_array(packer, (size_t) count);
for (Integer i = 0; i < count; i++) { msgpack_pack_int16(packer, attrs[i]); }
for (Integer i = 0; i < count; i++) {msgpack_pack_int16(packer, attrs[i]);}
});
}
@ -207,9 +210,9 @@ static void server_ui_default_colors_set(
Integer cterm_fg __unused,
Integer cterm_bg __unused
) {
if (rgb_fg != -1) { default_foreground = rgb_fg; }
if (rgb_bg != -1) { default_background = rgb_bg; }
if (rgb_sp != -1) { default_special = rgb_sp; }
if (rgb_fg != -1) {default_foreground = rgb_fg;}
if (rgb_bg != -1) {default_background = rgb_bg;}
if (rgb_sp != -1) {default_special = rgb_sp;}
send_msg_packing(
NvimServerMsgIdDefaultColorsChanged,
@ -223,7 +226,7 @@ static void server_ui_default_colors_set(
}
static void server_ui_set_title(UI *ui __unused, String title) {
if (title.size == 0) { return; }
if (title.size == 0) {return;}
send_msg_packing(NvimServerMsgIdSetTitle, ^(msgpack_packer *packer) {
msgpack_rpc_from_string(title, packer);
@ -271,6 +274,7 @@ void custom_ui_start(void) {
ui->mode_change = server_ui_mode_change;
ui->grid_scroll = server_ui_grid_scroll;
ui->hl_attr_define = server_ui_hl_attr_define;
ui->hl_group_set = server_hl_group_set;
ui->default_colors_set = server_ui_default_colors_set;
ui->raw_line = server_ui_raw_line;
ui->bell = server_ui_bell;
@ -352,7 +356,7 @@ void custom_ui_autocmds_groups(
static bool has_dirty_docs() {
FOR_ALL_BUFFERS(buffer) {
if (bufIsChanged(buffer)) { return true; }
if (bufIsChanged(buffer)) {return true;}
}
return false;
@ -366,7 +370,7 @@ static void pack_flush_data(RenderDataType type, pack_block body) {
static void send_dirty_status() {
const bool new_dirty_status = has_dirty_docs();
if (are_buffers_dirty == new_dirty_status) { return; }
if (are_buffers_dirty == new_dirty_status) {return;}
are_buffers_dirty = new_dirty_status;
@ -405,7 +409,7 @@ static int background_for(HlAttrs attrs) {
static void send_colorscheme() {
// It seems that the highlight groupt only gets updated when the screen is
// redrawn. Since there's a guard var, probably it's safe to call it here...
if (need_highlight_changed) { highlight_changed(); }
if (need_highlight_changed) {highlight_changed();}
const HlAttrs visualAttrs = syn_attr2entry(highlight_attr[HLF_V]);
const HlAttrs dirAttrs = syn_attr2entry(highlight_attr[HLF_D]);
@ -459,7 +463,7 @@ static void server_ui_main(UIBridgeData *bridge, UI *ui) {
// We have to manually trigger this to initially get the colorscheme.
send_colorscheme();
while (!bridge_data.stop) { loop_poll_events(&loop, -1); }
while (!bridge_data.stop) {loop_poll_events(&loop, -1);}
ui_bridge_stopped(bridge);
loop_close(&loop, false);

View File

@ -15,6 +15,7 @@
1929B13ACA836714CD801F41 /* ConditionVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B4CC2D4AF391223461A2 /* ConditionVariable.swift */; };
1929B14D2EBC34BCFEC78ACB /* CellAttributesCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB19DD03ECD6ECC35F94 /* CellAttributesCollection.swift */; };
1929B1A7CC32FD7D05646B98 /* AttributesRunDrawer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB7E3430BD3FD88A7698 /* AttributesRunDrawer.swift */; };
1929B21A36207DF558518597 /* FifoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA35C7CA9FEA9FFA3A51 /* FifoCache.swift */; };
1929B2DB631E6EB5C3452B68 /* MyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BAF033A398BFBC2A7890 /* MyView.swift */; };
1929B2E9F089A9E2800B67F2 /* NimbleCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF88DE64FC62AFFCBC84 /* NimbleCommons.swift */; };
1929B326D5117A670105C209 /* 2.json in Resources */ = {isa = PBXBuildFile; fileRef = 1929B0522C47787B50071806 /* 2.json */; };
@ -28,7 +29,6 @@
1929B4632DE08273F990806F /* Runs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B06A73BE6DAA2679AAA2 /* Runs.swift */; };
1929B4C729F3713A6BBEAEC9 /* OSLogCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B39C7DCDA4E9D5220CD8 /* OSLogCommons.swift */; };
1929B5C5DB438B66EC131EDE /* Defs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF14AE831C6832659B66 /* Defs.swift */; };
1929B6776A1D11409335FAAB /* SimpleCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B60D1775A75D7C0F6721 /* SimpleCache.swift */; };
1929B70D3BA20F66CAFF08C8 /* CoreCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BAB9FFE8345228B559EC /* CoreCommons.swift */; };
1929B738A3677586230704F7 /* MessagePackCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9290D503536FFDA9C49 /* MessagePackCommons.swift */; };
1929B74691D92B9F369787E5 /* ColorUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDE2C6003A6EDC02129C /* ColorUtils.swift */; };
@ -115,7 +115,6 @@
4BF01CE52235022300411218 /* FontUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B96A876229DA394F906E /* FontUtils.swift */; };
4BF01CE62235022300411218 /* CellAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE45756C88F8B43804D2 /* CellAttributes.swift */; };
4BF01CE72235022300411218 /* UGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D83D7E150F518D49FE /* UGrid.swift */; };
4BF01CE82235022300411218 /* SimpleCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B60D1775A75D7C0F6721 /* SimpleCache.swift */; };
4BF01CE92235022300411218 /* Runs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B06A73BE6DAA2679AAA2 /* Runs.swift */; };
4BF01CEA2235022300411218 /* Typesetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B47330DAD129520A2273 /* Typesetter.swift */; };
4BF01CEB2235022300411218 /* Geometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B73455764E42DACF6BB8 /* Geometry.swift */; };
@ -140,10 +139,16 @@
4BF18533213142FA00954FE7 /* CellAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE45756C88F8B43804D2 /* CellAttributes.swift */; };
4BF18534213142FA00954FE7 /* UGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D83D7E150F518D49FE /* UGrid.swift */; };
4BF18535213142FA00954FE7 /* AttributesRunDrawer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB7E3430BD3FD88A7698 /* AttributesRunDrawer.swift */; };
4BF18536213142FA00954FE7 /* SimpleCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B60D1775A75D7C0F6721 /* SimpleCache.swift */; };
4BF18537213142FA00954FE7 /* Runs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B06A73BE6DAA2679AAA2 /* Runs.swift */; };
4BF18538213142FA00954FE7 /* Typesetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B47330DAD129520A2273 /* Typesetter.swift */; };
4BF18C5D1FD2EEE400DF95D1 /* NvimView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF18C5C1FD2EEE400DF95D1 /* NvimView.h */; settings = {ATTRIBUTES = (Public, ); }; };
4BF4FD7724169FD60025ACC4 /* FifoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA35C7CA9FEA9FFA3A51 /* FifoCache.swift */; };
4BF4FD782416A0180025ACC4 /* MessagePack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB1F5CA209740E900EC394A /* MessagePack.framework */; };
4BF4FD792416A0180025ACC4 /* MessagePack.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB1F5CA209740E900EC394A /* MessagePack.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
4BF4FD7B2416A03B0025ACC4 /* MessagePack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB1F5CA209740E900EC394A /* MessagePack.framework */; };
4BF4FD7C2416A03B0025ACC4 /* MessagePack.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB1F5CA209740E900EC394A /* MessagePack.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
4BF4FD7E2416A06D0025ACC4 /* FifoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA35C7CA9FEA9FFA3A51 /* FifoCache.swift */; };
4BF4FD802416A18E0025ACC4 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BF4FD7F2416A18E0025ACC4 /* GameKit.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -229,6 +234,28 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4BF4FD7A2416A0180025ACC4 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
4BF4FD792416A0180025ACC4 /* MessagePack.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
4BF4FD7D2416A03B0025ACC4 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
4BF4FD7C2416A03B0025ACC4 /* MessagePack.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@ -248,7 +275,6 @@
1929B47330DAD129520A2273 /* Typesetter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Typesetter.swift; sourceTree = "<group>"; };
1929B4CC2D4AF391223461A2 /* ConditionVariable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConditionVariable.swift; sourceTree = "<group>"; };
1929B52174EC68D2974B5BAE /* UiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiBridge.swift; sourceTree = "<group>"; };
1929B60D1775A75D7C0F6721 /* SimpleCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleCache.swift; sourceTree = "<group>"; };
1929B73455764E42DACF6BB8 /* Geometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Geometry.swift; sourceTree = "<group>"; };
1929B7398AD1DE525FA53E38 /* server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = "<group>"; };
1929B8619FD13BC2570CBFB2 /* 1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = 1.json; sourceTree = "<group>"; };
@ -257,6 +283,7 @@
1929B9C55A79D97272894F5D /* SwiftCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftCommons.swift; sourceTree = "<group>"; };
1929B9D7F040B8B9E2F038DF /* FontTrait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FontTrait.swift; sourceTree = "<group>"; };
1929B9D83D7E150F518D49FE /* UGrid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UGrid.swift; sourceTree = "<group>"; };
1929BA35C7CA9FEA9FFA3A51 /* FifoCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FifoCache.swift; sourceTree = "<group>"; };
1929BAB0B8BA4E6CDF5C56F3 /* NvimView+Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+Types.swift"; sourceTree = "<group>"; };
1929BAB9FFE8345228B559EC /* CoreCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreCommons.swift; sourceTree = "<group>"; };
1929BAF033A398BFBC2A7890 /* MyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyView.swift; sourceTree = "<group>"; };
@ -332,6 +359,7 @@
4BF1852921313EE500954FE7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4BF18C5A1FD2E72D00DF95D1 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = neovim/src/nvim; sourceTree = "<group>"; };
4BF18C5C1FD2EEE400DF95D1 /* NvimView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NvimView.h; sourceTree = "<group>"; };
4BF4FD7F2416A18E0025ACC4 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -381,6 +409,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4BF4FD802416A18E0025ACC4 /* GameKit.framework in Frameworks */,
4BF4FD7B2416A03B0025ACC4 /* MessagePack.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -388,6 +418,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4BF4FD782416A0180025ACC4 /* MessagePack.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -415,7 +446,6 @@
1929BE45756C88F8B43804D2 /* CellAttributes.swift */,
1929B9D83D7E150F518D49FE /* UGrid.swift */,
1929BB7E3430BD3FD88A7698 /* AttributesRunDrawer.swift */,
1929B60D1775A75D7C0F6721 /* SimpleCache.swift */,
1929B06A73BE6DAA2679AAA2 /* Runs.swift */,
1929B47330DAD129520A2273 /* Typesetter.swift */,
1929B73455764E42DACF6BB8 /* Geometry.swift */,
@ -526,6 +556,7 @@
1929BAB0B8BA4E6CDF5C56F3 /* NvimView+Types.swift */,
1929B4CC2D4AF391223461A2 /* ConditionVariable.swift */,
1929B03EB461210D48D47510 /* NvimCursorModeShape.generated.swift */,
1929BA35C7CA9FEA9FFA3A51 /* FifoCache.swift */,
);
path = NvimView;
sourceTree = "<group>";
@ -549,6 +580,7 @@
4B90F06F1FD2B9F1008A39E0 /* Frameworks */ = {
isa = PBXGroup;
children = (
4BF4FD7F2416A18E0025ACC4 /* GameKit.framework */,
4B022603224AAE770052362B /* PureLayout.framework */,
4B379CCC2248CFB6004B89B4 /* CoreFoundation.framework */,
4BEBC239215FD19C007113C4 /* Socket.framework */,
@ -689,6 +721,7 @@
4BF01CC82235015E00411218 /* Sources */,
4BF01CC92235015E00411218 /* Frameworks */,
4BF01CCA2235015E00411218 /* Resources */,
4BF4FD7D2416A03B0025ACC4 /* Embed Frameworks */,
);
buildRules = (
);
@ -706,6 +739,7 @@
4BF1851C21313EE300954FE7 /* Sources */,
4BF1851D21313EE300954FE7 /* Frameworks */,
4BF1851E21313EE300954FE7 /* Resources */,
4BF4FD7A2416A0180025ACC4 /* Embed Frameworks */,
);
buildRules = (
);
@ -914,7 +948,6 @@
1929B9A949EE85C27FF66367 /* UGrid.swift in Sources */,
4BB1EFB2224B71ED00A5CD5A /* RxNeovimApi.generated.swift in Sources */,
1929BC8495028D66F0A7D618 /* AttributesRunDrawer.swift in Sources */,
1929B6776A1D11409335FAAB /* SimpleCache.swift in Sources */,
1929B4632DE08273F990806F /* Runs.swift in Sources */,
1929B7D2EB80FEA7BFBC3D2C /* Typesetter.swift in Sources */,
1929BDD254F59FC0F5B800E7 /* Geometry.swift in Sources */,
@ -935,6 +968,7 @@
1929BA25DA32AE80C527BB2A /* NvimView+Types.swift in Sources */,
1929B13ACA836714CD801F41 /* ConditionVariable.swift in Sources */,
1929B3D4281D2E30A9603368 /* NvimCursorModeShape.generated.swift in Sources */,
1929B21A36207DF558518597 /* FifoCache.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -952,6 +986,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4BF4FD7E2416A06D0025ACC4 /* FifoCache.swift in Sources */,
4BF01CF2223502DB00411218 /* CoreCommons.swift in Sources */,
4BF01CF1223502D400411218 /* Defs.swift in Sources */,
4BF01CF0223502CC00411218 /* SwiftCommons.swift in Sources */,
@ -962,7 +997,6 @@
4BF01CE52235022300411218 /* FontUtils.swift in Sources */,
4BF01CE62235022300411218 /* CellAttributes.swift in Sources */,
4BF01CE72235022300411218 /* UGrid.swift in Sources */,
4BF01CE82235022300411218 /* SimpleCache.swift in Sources */,
4BF01CE92235022300411218 /* Runs.swift in Sources */,
4BF01CEA2235022300411218 /* Typesetter.swift in Sources */,
4BF01CEB2235022300411218 /* Geometry.swift in Sources */,
@ -977,6 +1011,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4BF4FD7724169FD60025ACC4 /* FifoCache.swift in Sources */,
4B6DFB39223592B90066BB43 /* OSLogCommons.swift in Sources */,
4B21ED53213D4AEC009FD017 /* CocoaCommons.swift in Sources */,
4BF18531213142F900954FE7 /* ColorUtils.swift in Sources */,
@ -984,7 +1019,6 @@
4BF18533213142FA00954FE7 /* CellAttributes.swift in Sources */,
4BF18534213142FA00954FE7 /* UGrid.swift in Sources */,
4BF18535213142FA00954FE7 /* AttributesRunDrawer.swift in Sources */,
4BF18536213142FA00954FE7 /* SimpleCache.swift in Sources */,
4BF18537213142FA00954FE7 /* Runs.swift in Sources */,
4BF18538213142FA00954FE7 /* Typesetter.swift in Sources */,
4BF1852321313EE400954FE7 /* AppDelegate.swift in Sources */,
@ -1148,7 +1182,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 344;
CURRENT_PROJECT_VERSION = 347;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -1211,7 +1245,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 344;
CURRENT_PROJECT_VERSION = 347;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -1241,7 +1275,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 344;
DYLIB_CURRENT_VERSION = 347;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
FRAMEWORK_VERSION = A;
@ -1263,7 +1297,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 344;
DYLIB_CURRENT_VERSION = 347;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
FRAMEWORK_VERSION = A;
@ -1368,6 +1402,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_WEAK = YES;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
INFOPLIST_FILE = DrawerPerf/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
@ -1384,6 +1419,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_WEAK = YES;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
INFOPLIST_FILE = DrawerPerf/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MTL_FAST_MATH = YES;

View File

@ -158,19 +158,23 @@ final class AttributesRunDrawer {
private func fontGlyphRuns(from attrsRun: AttributesRun, offset: CGPoint) -> [FontGlyphRun] {
let font = FontUtils.font(adding: attrsRun.attrs.fontTrait, to: self.font)
let typesetFunction = self.usesLigatures
? self.typesetter.fontGlyphRunsWithLigatures
: self.typesetter.fontGlyphRunsWithoutLigatures
let fontGlyphRuns = typesetFunction(
attrsRun.cells.map { Array($0.string.utf16) },
attrsRun.cells.startIndex,
CGPoint(x: offset.x, y: attrsRun.location.y + self.baselineOffset),
font,
self.cellSize.width
)
return fontGlyphRuns
if self.usesLigatures {
return self.typesetter.fontGlyphRunsWithLigatures(
nvimUtf16Cells: attrsRun.cells.map { Array($0.string.utf16) },
startColumn: attrsRun.cells.startIndex,
offset: CGPoint(x: offset.x, y: attrsRun.location.y + self.baselineOffset),
font: font,
cellWidth: self.cellSize.width
)
} else {
return self.typesetter.fontGlyphRunsWithoutLigatures(
nvimUtf16Cells: attrsRun.cells.map { Array($0.string.utf16) },
startColumn: attrsRun.cells.startIndex,
offset: CGPoint(x: offset.x, y: attrsRun.location.y + self.baselineOffset),
font: font,
cellWidth: self.cellSize.width
)
}
}
private func updateFontMetrics() {

View File

@ -4,8 +4,9 @@
*/
import Cocoa
import MessagePack
struct CellAttributes: CustomStringConvertible, Equatable {
public struct CellAttributes: CustomStringConvertible, Equatable {
public static func ==(left: CellAttributes, right: CellAttributes) -> Bool {
if left.foreground != right.foreground { return false }
@ -18,29 +19,51 @@ struct CellAttributes: CustomStringConvertible, Equatable {
return true
}
var fontTrait: FontTrait
public var fontTrait: FontTrait
var foreground: Int
var background: Int
var special: Int
var reverse: Bool
public var foreground: Int
public var background: Int
public var special: Int
public var effectiveForeground: Int {
return self.reverse ? self.background : self.foreground
public var reverse: Bool
public init(fontTrait: FontTrait, foreground: Int, background: Int, special: Int, reverse: Bool) {
self.fontTrait = fontTrait
self.foreground = foreground
self.background = background
self.special = special
self.reverse = reverse
}
public init(
withDict dict: [String: MessagePackValue],
with defaultAttributes: CellAttributes
) {
var fontTrait: FontTrait = []
if dict["bold"]?.boolValue == true { fontTrait = fontTrait.union(.bold) }
if dict["italic"]?.boolValue == true { fontTrait = fontTrait.union(.italic) }
if dict["underline"]?.boolValue == true { fontTrait = fontTrait.union(.underline) }
if dict["undercurl"]?.boolValue == true { fontTrait = fontTrait.union(.undercurl) }
self.fontTrait = fontTrait
self.foreground = dict["foreground"]?.intValue ?? defaultAttributes.foreground
self.background = dict["background"]?.intValue ?? defaultAttributes.background
self.special = dict["special"]?.intValue ?? defaultAttributes.special
self.reverse = dict["reverse"]?.boolValue ?? false
}
public var effectiveBackground: Int {
return self.reverse ? self.foreground : self.background
}
public var effectiveForeground: Int { self.reverse ? self.background : self.foreground }
public var effectiveBackground: Int { self.reverse ? self.foreground : self.background }
public var description: String {
return "CellAttributes<" +
"trait: \(String(self.fontTrait.rawValue, radix: 2)), " +
"fg: \(ColorUtils.colorIgnoringAlpha(self.foreground).hex), " +
"bg: \(ColorUtils.colorIgnoringAlpha(self.background).hex), " +
"sp: \(ColorUtils.colorIgnoringAlpha(self.special).hex), " +
"reverse: \(self.reverse)" +
">"
"CellAttributes<" +
"trait: \(String(self.fontTrait.rawValue, radix: 2)), " +
"fg: \(ColorUtils.colorIgnoringAlpha(self.foreground).hex), " +
"bg: \(ColorUtils.colorIgnoringAlpha(self.background).hex), " +
"sp: \(ColorUtils.colorIgnoringAlpha(self.special).hex), " +
"reverse: \(self.reverse)" +
">"
}
public var reversed: CellAttributes {
@ -50,21 +73,12 @@ struct CellAttributes: CustomStringConvertible, Equatable {
return result
}
func replacingDefaults(
with defaultAttributes: CellAttributes
) -> CellAttributes {
public func replacingDefaults(with defaultAttributes: CellAttributes) -> CellAttributes {
var result = self
if self.foreground == -1 {
result.foreground = defaultAttributes.foreground
}
if self.background == -1 {
result.background = defaultAttributes.background
}
if self.special == -1 {
result.special = defaultAttributes.special
}
if self.foreground == -1 { result.foreground = defaultAttributes.foreground }
if self.background == -1 { result.background = defaultAttributes.background }
if self.special == -1 { result.special = defaultAttributes.special }
return result
}

View File

@ -18,35 +18,21 @@ final class CellAttributesCollection {
reverse: false
)
init() {
self.attributes[CellAttributesCollection.defaultAttributesId]
= self.defaultAttributes
}
init() { self.attributes[CellAttributesCollection.defaultAttributesId] = self.defaultAttributes }
func attributes(of id: Int) -> CellAttributes? {
if id == Int.max {
return self.defaultAttributes.reversed
}
if id == Int.max { return self.defaultAttributes.reversed }
let absId = abs(id)
guard let attrs = self.attributes[absId] else {
return nil
}
if id < 0 {
return attrs.replacingDefaults(with: self.defaultAttributes).reversed
}
guard let attrs = self.attributes[absId] else { return nil }
if id < 0 { return attrs.replacingDefaults(with: self.defaultAttributes).reversed }
return attrs.replacingDefaults(with: self.defaultAttributes)
}
func set(attributes: CellAttributes, for id: Int) {
self.attributes[id] = attributes
if id == CellAttributesCollection.defaultAttributesId {
self.defaultAttributes = attributes
}
if id == CellAttributesCollection.defaultAttributesId { self.defaultAttributes = attributes }
}
private var attributes: [Int: CellAttributes] = [:]

View File

@ -5,39 +5,30 @@
import Cocoa
private let colorCache = SimpleCache<Int, NSColor>(countLimit: 500)
private let cgColorCache = SimpleCache<Int, CGColor>(countLimit: 500)
final class ColorUtils {
/// ARGB
static func cgColorIgnoringAlpha(_ rgb: Int) -> CGColor {
if let color = cgColorCache.object(forKey: rgb) {
return color
}
if let color = cgColorCache.valueForKey(rgb) { return color }
let color = self.colorIgnoringAlpha(rgb).cgColor
cgColorCache.set(object: color, forKey: rgb)
cgColorCache.set(color, forKey: rgb)
return color
}
static func cgColorIgnoringAlpha(_ rgb: Int32) -> CGColor {
if let color = cgColorCache.object(forKey: Int(rgb)) {
return color
}
if let color = cgColorCache.valueForKey(Int(rgb)) { return color }
let color = self.colorIgnoringAlpha(Int(rgb)).cgColor
cgColorCache.set(object: color, forKey: Int(rgb))
cgColorCache.set(color, forKey: Int(rgb))
return color
}
/// ARGB
static func colorIgnoringAlpha(_ rgb: Int) -> NSColor {
if let color = colorCache.object(forKey: rgb) {
return color
}
if let color = colorCache.valueForKey(rgb) { return color }
// @formatter:off
let red = ((rgb >> 16) & 0xFF).cgf / 255.0;
@ -46,8 +37,11 @@ final class ColorUtils {
// @formatter:on
let color = NSColor(srgbRed: red, green: green, blue: blue, alpha: 1.0)
colorCache.set(object: color, forKey: rgb)
colorCache.set(color, forKey: rgb)
return color
}
}
private let colorCache = FifoCache<Int, NSColor>(count: 500)
private let cgColorCache = FifoCache<Int, CGColor>(count: 500)

View File

@ -19,6 +19,7 @@ class ConditionVariable {
while !self.posted {
self.condition.wait(until: Date(timeIntervalSinceNow: seconds))
self.posted = true
}
fn?()

View File

@ -0,0 +1,59 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
final class FifoCache<Key: Hashable, Value> {
init(count: Int) {
self.count = count
self.keyWriteIndex = 0
self.keys = Array(repeating: nil, count: count)
self.storage = Dictionary(minimumCapacity: count)
}
func set(_ value: Value, forKey key: Key) {
self.lock.lock()
defer { self.lock.unlock() }
self.keyWriteIndex = (self.keyWriteIndex + 1) % self.count
if let keyToDel = self.keys[self.keyWriteIndex] { self.storage.removeValue(forKey: keyToDel) }
self.keys[self.keyWriteIndex] = key
self.storage[key] = value
}
func valueForKey(_ key: Key) -> Value? { self.lock.withLock { self.storage[key] } }
private let count: Int
private var keys: Array<Key?>
private var keyWriteIndex: Int
private var storage: Dictionary<Key, Value>
private let lock = Lock()
}
fileprivate final class Lock {
init() { pthread_mutex_init(self.mutex, nil) }
deinit {
pthread_mutex_destroy(self.mutex)
self.mutex.deallocate()
}
func lock() { pthread_mutex_lock(self.mutex) }
func unlock() { pthread_mutex_unlock(self.mutex) }
func withLock<T>(_ body: () -> T) -> T {
self.lock()
defer { self.unlock() }
return body()
}
private let mutex = UnsafeMutablePointer<pthread_mutex_t>.allocate(capacity: 1)
}

View File

@ -24,7 +24,7 @@ extension FontTrait: Hashable {
final class FontUtils {
static func cellSize(of font: NSFont, linespacing: CGFloat, characterspacing: CGFloat) -> CGSize {
if let cached = cellSizeWithDefaultLinespacingCache.object(forKey: font) {
if let cached = cellSizeWithDefaultLinespacingCache.valueForKey(font) {
return CGSize(
width: characterspacing * cached.width,
height: ceil(linespacing * cached.height)
@ -41,13 +41,8 @@ final class FontUtils {
let descent = CTFontGetDescent(font)
let leading = CTFontGetLeading(font)
let cellSizeToCache = CGSize(
width: advancement.width,
height: ceil(ascent + descent + leading)
)
cellSizeWithDefaultLinespacingCache.set(
object: cellSizeToCache, forKey: font
)
let cellSizeToCache = CGSize(width: advancement.width, height: ceil(ascent + descent + leading))
cellSizeWithDefaultLinespacingCache.set(cellSizeToCache, forKey: font)
let cellSize = CGSize(
width: characterspacing * advancement.width,
@ -58,24 +53,16 @@ final class FontUtils {
}
static func font(adding trait: FontTrait, to font: NSFont) -> NSFont {
if trait.isEmpty {
return font
}
if trait.isEmpty { return font }
let sizedFontTrait = SizedFontTrait(trait: trait, size: font.pointSize)
if let cachedFont = fontCache.object(forKey: sizedFontTrait) {
return cachedFont
}
if let cachedFont = fontCache.valueForKey(sizedFontTrait) { return cachedFont }
var ctFontTrait: CTFontSymbolicTraits = []
if trait.contains(.bold) {
ctFontTrait.insert(.boldTrait)
}
if trait.contains(.bold) { ctFontTrait.insert(.boldTrait) }
if trait.contains(.italic) {
ctFontTrait.insert(.italicTrait)
}
if trait.contains(.italic) { ctFontTrait.insert(.italicTrait) }
guard let ctFont = CTFontCreateCopyWithSymbolicTraits(
font, 0.0, nil, ctFontTrait, ctFontTrait
@ -83,10 +70,10 @@ final class FontUtils {
return font
}
fontCache.set(object: ctFont, forKey: sizedFontTrait)
fontCache.set(ctFont, forKey: sizedFontTrait)
return ctFont
}
}
private let fontCache = SimpleCache<SizedFontTrait, NSFont>(countLimit: 100)
private let cellSizeWithDefaultLinespacingCache = SimpleCache<NSFont, CGSize>(countLimit: 100)
private let fontCache = FifoCache<SizedFontTrait, NSFont>(count: 100)
private let cellSizeWithDefaultLinespacingCache = FifoCache<NSFont, CGSize>(count: 100)

View File

@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.32.0</string>
<string>SNAPSHOT-347</string>
<key>CFBundleVersion</key>
<string>344</string>
<string>347</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Tae Won Ha. All rights reserved.</string>
<key>NSPrincipalClass</key>

View File

@ -70,6 +70,8 @@ extension NvimView {
fileURLWithPath: NSTemporaryDirectory()
).appendingPathComponent("vimr_\(self.uuid).sock").path
self.log.info("NVIM_LISTEN_ADDRESS=\(sockPath)")
self.api.msgpackRawStream
.subscribe(onNext: { [weak self] msg in
switch msg {

View File

@ -77,13 +77,10 @@ extension NvimView {
public var directoryForeground = NSColor.textColor
public init() {
}
public init() {}
public init(_ values: [Int]) {
if values.count < 5 {
preconditionFailure("We need 5 colors!")
}
if values.count < 5 { preconditionFailure("We need 5 colors!") }
let color = ColorUtils.colorIgnoringAlpha
@ -93,7 +90,9 @@ extension NvimView {
self.visualForeground = values[2] < 0 ? Theme.default.visualForeground : color(values[2])
self.visualBackground = values[3] < 0 ? Theme.default.visualBackground : color(values[3])
self.directoryForeground = values[4] < 0 ? Theme.default.directoryForeground : color(values[4])
self.directoryForeground = values[4] < 0
? Theme.default.directoryForeground
: color(values[4])
}
public var description: String {

View File

@ -379,7 +379,7 @@ extension NvimView {
) else {
self.bridgeLogger.error("Could not convert \(value)")
return
}
}
let theme = Theme(values)
self.bridgeLogger.debug(theme)

View File

@ -29,6 +29,7 @@ public class NvimView: NSView,
public var isRightOptionMeta = false
public let uuid = UUID()
public let api = RxNeovimApi()
public internal(set) var mode = CursorModeShape.normal
@ -117,6 +118,10 @@ public class NvimView: NSView,
}
}
public var defaultCellAttributes: CellAttributes {
self.cellAttributesCollection.defaultAttributes
}
override public var acceptsFirstResponder: Bool {
return true
}
@ -184,7 +189,6 @@ public class NvimView: NSView,
)
let bridge: UiBridge
let api = RxNeovimApi()
let ugrid = UGrid()
let cellAttributesCollection = CellAttributesCollection()

View File

@ -1,60 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import os
final class SimpleCache<K: Hashable, V> {
init(countLimit: Int? = nil) {
if let limit = countLimit {
self.cache.countLimit = limit
}
}
func object(forKey key: K) -> V? {
return self.cache.object(forKey: KeyBox(key))?.value
}
func set(object: V, forKey key: K) {
self.cache.setObject(ValueBox(object), forKey: KeyBox(key))
}
func removeObject(forKey key: K) {
cache.removeObject(forKey: KeyBox(key))
}
func removeAllObjects() {
cache.removeAllObjects()
}
private let cache = NSCache<KeyBox<K>, ValueBox<V>>()
private class ValueBox<T> {
fileprivate let value: T
fileprivate init(_ value: T) {
self.value = value
}
}
private class KeyBox<K: Hashable>: NSObject {
fileprivate let key: K
fileprivate init(_ key: K) {
self.key = key
}
override var hash: Int {
return key.hashValue
}
override func isEqual(_ object: Any?) -> Bool {
return self.key == (object as? KeyBox<K>)?.key
}
}
}

View File

@ -134,32 +134,26 @@ final class Typesetter {
return runs.flatMap { $0 }
}
private let ctRunsCache = SimpleCache<NSAttributedString, [CTRun]>(countLimit: 5000)
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.view)
private func ctRuns(from utf16Chars: Array<Unicode.UTF16.CodeUnit>, font: NSFont) -> [CTRun] {
if let ctRunsAndFont = self.ctRunsCache.valueForKey(utf16Chars),
font == ctRunsAndFont.font { return ctRunsAndFont.ctRuns }
let attrStr = NSAttributedString(
string: String(utf16CodeUnits: utf16Chars, count: utf16Chars.count),
attributes: [.font: font, .ligature: ligatureOption]
)
if let cachedCtRuns = self.ctRunsCache.object(forKey: attrStr) { return cachedCtRuns }
let ctLine = CTLineCreateWithAttributedString(attrStr)
guard let ctRuns = CTLineGetGlyphRuns(ctLine) as? [CTRun] else { return [] }
self.ctRunsCache.set(object: ctRuns, forKey: attrStr)
self.ctRunsCache.set(
CtRunsAndFont(ctRuns: ctRuns, font: font),
forKey: utf16Chars
)
return ctRuns
}
private struct NvimUtf16CellsRun {
var startColumn: Int
var nvimUtf16Cells: [[Unicode.UTF16.CodeUnit]]
var isSimple: Bool
}
private func groupSimpleAndNonSimpleChars(
nvimUtf16Cells: [[Unicode.UTF16.CodeUnit]],
font: NSFont
@ -257,24 +251,42 @@ final class Typesetter {
}
private func utf16Chars(from nvimUtf16Cells: [[Unicode.UTF16.CodeUnit]]) -> Array<UInt16> {
return nvimUtf16Cells.withUnsafeBufferPointer { pointer -> [UInt16] in
var count = 0
for i in 0..<pointer.count { count = count + pointer[i].count }
nvimUtf16Cells.withUnsafeBufferPointer { pointer -> [UInt16] in
let count = pointer.reduce(0) { acc, elem in acc + elem.count }
var result = Array(repeating: Unicode.UTF16.CodeUnit(), count: count)
var i = 0
for k in 0..<pointer.count {
let element = pointer[k]
if element.isEmpty { continue }
return Array<Unicode.UTF16.CodeUnit>(
unsafeUninitializedCapacity: count
) { resultPtr, initCount in
var i = 0
for k in 0..<pointer.count {
let element = pointer[k]
if element.isEmpty { continue }
for j in 0..<element.count { result[i + j] = element[j] }
for j in 0..<element.count { resultPtr[i + j] = element[j] }
i = i + element.count
i = i + element.count
}
initCount = count
}
return result
}
}
private let ctRunsCache = FifoCache<Array<Unicode.UTF16.CodeUnit>, CtRunsAndFont>(count: 5000)
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.view)
private struct CtRunsAndFont {
var ctRuns: [CTRun]
var font: NSFont
}
private struct NvimUtf16CellsRun {
var startColumn: Int
var nvimUtf16Cells: [[Unicode.UTF16.CodeUnit]]
var isSimple: Bool
}
}
private let ligatureOption = NSNumber(integerLiteral: 1)

View File

@ -15,8 +15,8 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>0.32.0</string>
<string>SNAPSHOT-347</string>
<key>CFBundleVersion</key>
<string>344</string>
<string>347</string>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

View File

@ -25,12 +25,54 @@ class NvimMsgPackTests: XCTestCase {
}
func testSth() {
nvim
.command(command: "pwd")
.subscribe(onCompleted: { print("completed") }, onError: { print($0) })
// .subscribe(onSuccess: { print($0) })
let colorNames = [
"Normal", // color and background-color
"Directory", // a
"StatusLine", // code background and foreground
"NonText", // hr and block quote border
"Question", // blockquote foreground
]
typealias HlResult = Dictionary<String, RxNeovimApi.Value>
typealias ColorNameHlResultTuple = (colorName: String, hlResult: HlResult)
typealias ColorNameObservableTuple = (colorName: String, observable: Observable<HlResult>)
Observable
.from(colorNames.map { colorName -> ColorNameObservableTuple in
(
colorName: colorName,
observable: self.nvim
.getHlByName(name: colorName, rgb: true)
.asObservable()
)
})
.flatMap { tuple -> Observable<(String, HlResult)> in
Observable.zip(Observable.just(tuple.colorName), tuple.observable)
}
.subscribe(onNext: { (tuple: ColorNameHlResultTuple) in
print(tuple)
})
.disposed(by: self.disposeBag)
// Observable
// .concat(colorNames.map { colorName in
// self.nvim
// .getHlByName(name: colorName, rgb: true)
// .asObservable()
// })
// .enumerated()
// .subscribe(onNext: { dict in print(dict) })
// .disposed(by: self.disposeBag)
// self.nvim
// .getHlByName(name: "Normal", rgb: true)
// .subscribe(onSuccess: { dict in
// guard let f = dict["foreground"]?.uint64Value,
// let b = dict["background"]?.uint64Value else { return }
// print(String(format: "%06X %06X", f, b))
// }, onError: { err in print(err) })
// .disposed(by: self.disposeBag)
sleep(1)
}

View File

@ -20,7 +20,11 @@ extension PrimitiveSequence where Element == Never, Trait == CompletableTrait {
func andThen(using body: () -> Completable) -> Completable { self.andThen(body()) }
func wait(onCompleted: (() -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil) throws {
func wait(
timeout: TimeInterval = 5,
onCompleted: (() -> Void)? = nil,
onError: ((Swift.Error) -> Void)? = nil
) throws {
var trigger = false
var err: Swift.Error? = nil
@ -46,7 +50,11 @@ extension PrimitiveSequence where Element == Never, Trait == CompletableTrait {
condition.broadcast()
})
while !trigger { condition.wait(until: Date(timeIntervalSinceNow: 5)) }
while !trigger {
condition.wait(until: Date(timeIntervalSinceNow: timeout))
trigger = true
}
disposable.dispose()
if let e = err { throw e }
@ -68,7 +76,7 @@ extension PrimitiveSequence where Trait == SingleTrait {
.ignoreElements()
}
func syncValue() -> Element? {
func syncValue(timeout: TimeInterval = 5) -> Element? {
var trigger = false
var value: Element?
@ -91,7 +99,11 @@ extension PrimitiveSequence where Trait == SingleTrait {
condition.broadcast()
})
while !trigger { condition.wait(until: Date(timeIntervalSinceNow: 5)) }
while !trigger {
condition.wait(until: Date(timeIntervalSinceNow: timeout))
trigger = true
}
disposable.dispose()
return value

View File

@ -11,7 +11,7 @@ import io
void_func_template = Template('''\
func ${func_name}(${args}
public func ${func_name}(${args}
expectsReturnValue: Bool = false
) -> Completable {
@ -34,7 +34,7 @@ void_func_template = Template('''\
''')
get_mode_func_template = Template('''\
func ${func_name}(${args}
public func ${func_name}(${args}
) -> Single<${result_type}> {
let params: [RxNeovimApi.Value] = [
@ -53,7 +53,7 @@ get_mode_func_template = Template('''\
''')
func_template = Template('''\
func ${func_name}(${args}
public func ${func_name}(${args}
errWhenBlocked: Bool = true
) -> Single<${result_type}> {

View File

@ -14,19 +14,21 @@
1929B0F599D1F62C7BE53D2C /* HttpServerMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1DC584C89C477E83FA2 /* HttpServerMiddleware.swift */; };
1929B1837C750CADB3A5BCB9 /* OpenQuicklyFileViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */; };
1929B20CE35B43BB1CE023BA /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BC2F05E9A5C0DB039739 /* Theme.swift */; };
1929B223C6E97C090474B2C2 /* Resources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BC40B7B7708D8BE3A272 /* Resources.swift */; };
1929B250DB3FB395A700FE8C /* RpcEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBF0944940845485A512 /* RpcEvents.swift */; };
1929B29B95AD176D57942E08 /* UiRootReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B457B9D0FA4D21F3751E /* UiRootReducer.swift */; };
1929B29FF537A339CF4075BD /* CssUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA05F1FE30CA74F006C4 /* CssUtils.swift */; };
1929B2D56C4652E251C23AD4 /* DefaultShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B93256AF7F9137223E36 /* DefaultShortcuts.swift */; };
1929B3217A7A3D79E28C80DB /* PrefWindowReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B49E6924847AD085C8C9 /* PrefWindowReducer.swift */; };
1929B3557317755A43513B17 /* OpenQuicklyWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B71A92C24FEFE79A851E /* OpenQuicklyWindow.swift */; };
1929B370A275F8C70AD5AA08 /* UrlCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B11D672134E52A256A7F /* UrlCommonsTest.swift */; };
1929B376DB09AB5FDBF42BA1 /* MainWindow+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B41F704A4D67621197ED /* MainWindow+Types.swift */; };
1929B3A6C332FFAAEC7FD219 /* MainWindow+CustomTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B71B4BB6550F5BC6D4CF /* MainWindow+CustomTitle.swift */; };
1929B3AC66EFE35D68C020E3 /* PreviewToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BFB0F294F3714D5E095F /* PreviewToolReducer.swift */; };
1929B3AC66EFE35D68C020E3 /* MarkdownToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BFB0F294F3714D5E095F /* MarkdownToolReducer.swift */; };
1929B4219A68586E2CED6E96 /* FileMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B333D8752E2E68F35122 /* FileMonitor.swift */; };
1929B443B7AB2176A7818CA1 /* fuzzy_match.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1B01340283D6AAD6B06 /* fuzzy_match.cc */; };
1929B4B00D7BB191A9A6532D /* HtmlPreviewToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE5AEA3D0980860EED50 /* HtmlPreviewToolReducer.swift */; };
1929B4B70926DE113E6BF990 /* PreviewReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE37AA2843779CAFA76F /* PreviewReducer.swift */; };
1929B4B70926DE113E6BF990 /* MarkdownPreviewReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE37AA2843779CAFA76F /* MarkdownPreviewReducer.swift */; };
1929B4E54E2F13A7F5F2B682 /* BufferListReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B67A10E6BB2986B2416E /* BufferListReducer.swift */; };
1929B4E8B916008399CD5D3A /* OSLogCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE867BD8F0ED0246CC94 /* OSLogCommons.swift */; };
1929B4F0612224E594E89B92 /* AppearancePref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0FBFB766042CF06E463 /* AppearancePref.swift */; };
@ -38,7 +40,7 @@
1929B59FA5C286E010F70BEE /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BFC0A5A9C6DB09BE1368 /* Types.swift */; };
1929B5A0EDD1119CFF7BB84C /* Defs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7F7A4B3FD52263D211D /* Defs.swift */; };
1929B5A2EE366F79ED32744C /* KeysPrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B88B5FA08E897A3C2168 /* KeysPrefReducer.swift */; };
1929B5C1BABBC0D09D97C3EF /* PreviewMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B617C229B19DB3E987B8 /* PreviewMiddleware.swift */; };
1929B5C1BABBC0D09D97C3EF /* MarkdownPreviewMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B617C229B19DB3E987B8 /* MarkdownPreviewMiddleware.swift */; };
1929B6460862447A31B5B082 /* ImageAndTextTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDC3F82CB4CB4FE56D1B /* ImageAndTextTableCell.swift */; };
1929B66F795867B8C07FAAD4 /* DictionaryCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9355C892BEBA7496C71 /* DictionaryCommonsTest.swift */; };
1929B67DA3EB21A631EF1DBB /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
@ -46,11 +48,10 @@
1929B6C0393DE40E34F4A49A /* ToolsPrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B694508FB5FDE607513A /* ToolsPrefReducer.swift */; };
1929B6D8F5FC723B7109031F /* OpenQuicklyReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B12CE56A9B36980288A4 /* OpenQuicklyReducer.swift */; };
1929B71381946860626E5224 /* FileBrowserReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDC8F5D48578A90236E9 /* FileBrowserReducer.swift */; };
1929B71610FF1DC6E459BA49 /* PreviewUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B8EF9A9F5ACC175452BD /* PreviewUtils.swift */; };
1929B8DDACEB28E6672AEC42 /* MainWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6E01216D49BB9F3B6A3 /* MainWindow.swift */; };
1929B8E90A1378E494D481E7 /* PrefUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7BB3E4B3DC96284B686 /* PrefUtilsTest.swift */; };
1929B8F498D1E7C53F572CE2 /* KeysPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B14A5949FB64C4B2646F /* KeysPref.swift */; };
1929B8FB248D71BF88A35761 /* PreviewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6C6C7792B05164B0216 /* PreviewTool.swift */; };
1929B8FB248D71BF88A35761 /* MarkdownTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6C6C7792B05164B0216 /* MarkdownTool.swift */; };
1929B9318D32146D58BB38EC /* AppKitCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70931D60E04200E12030 /* AppKitCommons.swift */; };
1929B98F94536E3912AD9F3B /* ArrayCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BAF13FAD5DA8D3762367 /* ArrayCommonsTest.swift */; };
1929B990A143763A56CFCED0 /* PrefMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B364460D86F17E80943C /* PrefMiddleware.swift */; };
@ -63,6 +64,7 @@
1929BB67CAAD4F6CBD38DF0A /* RxRedux.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B66A5E2D00EA143AFD86 /* RxRedux.swift */; };
1929BB85B2D30E548A32663D /* ShortcutsPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0E9B2F018D3E31D4B0B /* ShortcutsPref.swift */; };
1929BBE28654E4307AF1E2FD /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BC2F05E9A5C0DB039739 /* Theme.swift */; };
1929BC64D3C195A92BE3FD64 /* HtmlPreviewMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B18E9BE35750BF2BA571 /* HtmlPreviewMiddleware.swift */; };
1929BCC7908DD899999B70BE /* AppearancePrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BED01F5D94BFCA4CF80F /* AppearancePrefReducer.swift */; };
1929BCC9D3604933DFF07E2E /* FileBrowser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA5C7099CDEB04B76BA4 /* FileBrowser.swift */; };
1929BCF7F7B9CC5499A3F506 /* AdvancedPrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7039C5689CE45F53888 /* AdvancedPrefReducer.swift */; };
@ -312,6 +314,7 @@
1929B1534B8857C519D7C0FB /* FileItem+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FileItem+CoreDataProperties.h"; sourceTree = "<group>"; };
1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyFileViewRow.swift; sourceTree = "<group>"; };
1929B17B1BC7CA08DC76495C /* FileItem+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FileItem+CoreDataProperties.m"; sourceTree = "<group>"; };
1929B18E9BE35750BF2BA571 /* HtmlPreviewMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlPreviewMiddleware.swift; sourceTree = "<group>"; };
1929B1B01340283D6AAD6B06 /* fuzzy_match.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fuzzy_match.cc; path = FuzzyMatcher/fuzzy_match.cc; sourceTree = "<group>"; };
1929B1DC584C89C477E83FA2 /* HttpServerMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpServerMiddleware.swift; sourceTree = "<group>"; };
1929B230EE8F1428980988F0 /* RpcAppearanceEpic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RpcAppearanceEpic.swift; sourceTree = "<group>"; };
@ -322,7 +325,7 @@
1929B457B9D0FA4D21F3751E /* UiRootReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiRootReducer.swift; sourceTree = "<group>"; };
1929B49E6924847AD085C8C9 /* PrefWindowReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefWindowReducer.swift; sourceTree = "<group>"; };
1929B5D45C9792BBE76B8AFF /* StringCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringCommonsTest.swift; sourceTree = "<group>"; };
1929B617C229B19DB3E987B8 /* PreviewMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewMiddleware.swift; sourceTree = "<group>"; };
1929B617C229B19DB3E987B8 /* MarkdownPreviewMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownPreviewMiddleware.swift; sourceTree = "<group>"; };
1929B656C04BA6F950BFA2F5 /* FuzzySearch.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = FuzzySearch.xcdatamodel; sourceTree = "<group>"; };
1929B66A5E2D00EA143AFD86 /* RxRedux.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxRedux.swift; sourceTree = "<group>"; };
1929B672CE187B4D3EA1D3EE /* fuzzy_match.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = fuzzy_match.hh; path = FuzzyMatcher/fuzzy_match.hh; sourceTree = "<group>"; };
@ -330,7 +333,7 @@
1929B694508FB5FDE607513A /* ToolsPrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolsPrefReducer.swift; sourceTree = "<group>"; };
1929B6AD3396160AA2C46919 /* Debouncer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Debouncer.swift; sourceTree = "<group>"; };
1929B6C215ACCBE12672A8D7 /* RxSwiftCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxSwiftCommonsTest.swift; sourceTree = "<group>"; };
1929B6C6C7792B05164B0216 /* PreviewTool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewTool.swift; sourceTree = "<group>"; };
1929B6C6C7792B05164B0216 /* MarkdownTool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownTool.swift; sourceTree = "<group>"; };
1929B6E01216D49BB9F3B6A3 /* MainWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindow.swift; sourceTree = "<group>"; };
1929B7039C5689CE45F53888 /* AdvancedPrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedPrefReducer.swift; sourceTree = "<group>"; };
1929B714EB137AE448CE8ABD /* MainWindow+Delegates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MainWindow+Delegates.swift"; sourceTree = "<group>"; };
@ -345,12 +348,12 @@
1929B84E4B53B05F5434E464 /* lang.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lang.h; path = "../../third-party/libag/include/lang.h"; sourceTree = "<group>"; };
1929B85023B042C485409CE1 /* HtmlPreviewTool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlPreviewTool.swift; sourceTree = "<group>"; };
1929B88B5FA08E897A3C2168 /* KeysPrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeysPrefReducer.swift; sourceTree = "<group>"; };
1929B8EF9A9F5ACC175452BD /* PreviewUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewUtils.swift; sourceTree = "<group>"; };
1929B93256AF7F9137223E36 /* DefaultShortcuts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultShortcuts.swift; sourceTree = "<group>"; };
1929B9355C892BEBA7496C71 /* DictionaryCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryCommonsTest.swift; sourceTree = "<group>"; };
1929B9695325580C7100B44C /* ignore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ignore.h; path = "../../third-party/libag/include/ignore.h"; sourceTree = "<group>"; };
1929B98192F6873508F8D76A /* FileItem+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FileItem+CoreDataClass.m"; sourceTree = "<group>"; };
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationCommons.swift; sourceTree = "<group>"; };
1929BA05F1FE30CA74F006C4 /* CssUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CssUtils.swift; sourceTree = "<group>"; };
1929BA43449BA41666CD55ED /* BufferList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferList.swift; sourceTree = "<group>"; };
1929BA5854064776A5C38257 /* decompress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = decompress.h; path = "../../third-party/libag/include/decompress.h"; sourceTree = "<group>"; };
1929BA5C7099CDEB04B76BA4 /* FileBrowser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileBrowser.swift; sourceTree = "<group>"; };
@ -364,6 +367,7 @@
1929BBE0A534F2F6009D31BE /* AdvencedPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvencedPref.swift; sourceTree = "<group>"; };
1929BBF0944940845485A512 /* RpcEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RpcEvents.swift; sourceTree = "<group>"; };
1929BC2F05E9A5C0DB039739 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
1929BC40B7B7708D8BE3A272 /* Resources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Resources.swift; sourceTree = "<group>"; };
1929BC6D45B7E14D4D75D4E6 /* com.qvacua.VimR.vim */ = {isa = PBXFileReference; lastKnownFileType = file.vim; path = com.qvacua.VimR.vim; sourceTree = "<group>"; };
1929BCE3E156C06EDF1F2806 /* FileOutlineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileOutlineView.swift; sourceTree = "<group>"; };
1929BD2CA8DD198A6BCDBCB7 /* ThemedTableSubviews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemedTableSubviews.swift; sourceTree = "<group>"; };
@ -372,13 +376,13 @@
1929BDC3F82CB4CB4FE56D1B /* ImageAndTextTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAndTextTableCell.swift; sourceTree = "<group>"; };
1929BDC8F5D48578A90236E9 /* FileBrowserReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileBrowserReducer.swift; sourceTree = "<group>"; };
1929BE168F31344B69E61B62 /* PrefWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefWindow.swift; sourceTree = "<group>"; };
1929BE37AA2843779CAFA76F /* PreviewReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewReducer.swift; sourceTree = "<group>"; };
1929BE37AA2843779CAFA76F /* MarkdownPreviewReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownPreviewReducer.swift; sourceTree = "<group>"; };
1929BE5AEA3D0980860EED50 /* HtmlPreviewToolReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlPreviewToolReducer.swift; sourceTree = "<group>"; };
1929BE6AB18FA655A8A9DA73 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = "../../third-party/libag/include/util.h"; sourceTree = "<group>"; };
1929BE867BD8F0ED0246CC94 /* OSLogCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSLogCommons.swift; sourceTree = "<group>"; };
1929BED01F5D94BFCA4CF80F /* AppearancePrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearancePrefReducer.swift; sourceTree = "<group>"; };
1929BF230875DED6CD7AB3EB /* ShortcutItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutItem.swift; sourceTree = "<group>"; };
1929BFB0F294F3714D5E095F /* PreviewToolReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewToolReducer.swift; sourceTree = "<group>"; };
1929BFB0F294F3714D5E095F /* MarkdownToolReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownToolReducer.swift; sourceTree = "<group>"; };
1929BFC0A5A9C6DB09BE1368 /* Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; };
4B004BCB21063B600043A396 /* DictionaryDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DictionaryDecoder.swift; path = ../../Carthage/Checkouts/DictionaryCoding/Sources/DictionaryCoding/DictionaryDecoder.swift; sourceTree = "<group>"; };
4B004BCC21063B600043A396 /* DictionaryCodingKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DictionaryCodingKey.swift; path = ../../Carthage/Checkouts/DictionaryCoding/Sources/DictionaryCoding/DictionaryCodingKey.swift; sourceTree = "<group>"; };
@ -599,7 +603,7 @@
isa = PBXGroup;
children = (
1929BD4149D5A25C82064DD8 /* UiRoot.swift */,
1929B6C6C7792B05164B0216 /* PreviewTool.swift */,
1929B6C6C7792B05164B0216 /* MarkdownTool.swift */,
1929BA43449BA41666CD55ED /* BufferList.swift */,
1929BC56ADBA3275E7A0A598 /* Preferences */,
1929B1645977E0AEFE53193D /* File Browser */,
@ -626,8 +630,8 @@
1929B7A68B7109CEFAF105E8 /* AppDelegateReducer.swift */,
1929B457B9D0FA4D21F3751E /* UiRootReducer.swift */,
1929BD83A13BF133741766CC /* MainWindowReducer.swift */,
1929BE37AA2843779CAFA76F /* PreviewReducer.swift */,
1929BFB0F294F3714D5E095F /* PreviewToolReducer.swift */,
1929BE37AA2843779CAFA76F /* MarkdownPreviewReducer.swift */,
1929BFB0F294F3714D5E095F /* MarkdownToolReducer.swift */,
1929B12CE56A9B36980288A4 /* OpenQuicklyReducer.swift */,
1929BDC8F5D48578A90236E9 /* FileBrowserReducer.swift */,
1929B67A10E6BB2986B2416E /* BufferListReducer.swift */,
@ -745,9 +749,10 @@
1929BFA93DC859DD76C46192 /* Middlewares */ = {
isa = PBXGroup;
children = (
1929B617C229B19DB3E987B8 /* PreviewMiddleware.swift */,
1929B617C229B19DB3E987B8 /* MarkdownPreviewMiddleware.swift */,
1929B1DC584C89C477E83FA2 /* HttpServerMiddleware.swift */,
1929B364460D86F17E80943C /* PrefMiddleware.swift */,
1929B18E9BE35750BF2BA571 /* HtmlPreviewMiddleware.swift */,
);
name = Middlewares;
sourceTree = "<group>";
@ -1003,9 +1008,10 @@
1929B02440BC99C42F9EBD45 /* NetUtils.m */,
1929BADEB143008EFA6F3318 /* NetUtils.h */,
1929B6AD3396160AA2C46919 /* Debouncer.swift */,
1929B8EF9A9F5ACC175452BD /* PreviewUtils.swift */,
1929B8241CDE58F7AAF89AE4 /* PrefUtils.swift */,
1929B333D8752E2E68F35122 /* FileMonitor.swift */,
1929BC40B7B7708D8BE3A272 /* Resources.swift */,
1929BA05F1FE30CA74F006C4 /* CssUtils.swift */,
);
name = Utils;
sourceTree = "<group>";
@ -1226,13 +1232,13 @@
1929BB4A9B2FA42A64CCCC76 /* MainWindowReducer.swift in Sources */,
4BF70ED623D1B54F009E51E9 /* ScoredUrl.m in Sources */,
4BF70EC823D1B3F9009E51E9 /* FuzzyMatcherPool.swift in Sources */,
1929B8FB248D71BF88A35761 /* PreviewTool.swift in Sources */,
1929B8FB248D71BF88A35761 /* MarkdownTool.swift in Sources */,
4B917E5F2334D52D00752149 /* EonilFSEvents.swift in Sources */,
1929B4B70926DE113E6BF990 /* PreviewReducer.swift in Sources */,
1929B5C1BABBC0D09D97C3EF /* PreviewMiddleware.swift in Sources */,
1929B4B70926DE113E6BF990 /* MarkdownPreviewReducer.swift in Sources */,
1929B5C1BABBC0D09D97C3EF /* MarkdownPreviewMiddleware.swift in Sources */,
1929B0F599D1F62C7BE53D2C /* HttpServerMiddleware.swift in Sources */,
4B004BD321063B600043A396 /* DictionaryEncoder.swift in Sources */,
1929B3AC66EFE35D68C020E3 /* PreviewToolReducer.swift in Sources */,
1929B3AC66EFE35D68C020E3 /* MarkdownToolReducer.swift in Sources */,
1929B59FA5C286E010F70BEE /* Types.swift in Sources */,
1929B6D8F5FC723B7109031F /* OpenQuicklyReducer.swift in Sources */,
4BF70EE123D1B5B3009E51E9 /* FileScanBaton.m in Sources */,
@ -1258,7 +1264,6 @@
4BF70EEA23D1B5FF009E51E9 /* CoreDataStack.swift in Sources */,
1929B990A143763A56CFCED0 /* PrefMiddleware.swift in Sources */,
1929BA76A1D97D8226F7CFB1 /* Debouncer.swift in Sources */,
1929B71610FF1DC6E459BA49 /* PreviewUtils.swift in Sources */,
1929BFDE22D155F7C4B19E96 /* HtmlPreviewTool.swift in Sources */,
1929B4B00D7BB191A9A6532D /* HtmlPreviewToolReducer.swift in Sources */,
4BF70ED223D1B4AF009E51E9 /* FoundationCommons.m in Sources */,
@ -1296,6 +1301,9 @@
1929B443B7AB2176A7818CA1 /* fuzzy_match.cc in Sources */,
1929BF5D0EFCC56A733BB4B7 /* FuzzySearch.xcdatamodel in Sources */,
1929B4219A68586E2CED6E96 /* FileMonitor.swift in Sources */,
1929B223C6E97C090474B2C2 /* Resources.swift in Sources */,
1929BC64D3C195A92BE3FD64 /* HtmlPreviewMiddleware.swift in Sources */,
1929B29FF537A339CF4075BD /* CssUtils.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1427,7 +1435,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 344;
CURRENT_PROJECT_VERSION = 347;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -1487,7 +1495,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 344;
CURRENT_PROJECT_VERSION = 347;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;

View File

@ -48,9 +48,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
initialAppState = .default
}
initialAppState.mainWindowTemplate.htmlPreview.server = Marked(
baseServerUrl.appendingPathComponent(HtmlPreviewToolReducer.selectFirstPath)
)
initialAppState.mainWindowTemplate.htmlPreview.server = nil
self.context = Context(baseServerUrl: baseServerUrl, state: initialAppState)
self.emit = self.context.actionEmitter.typedEmit()

View File

@ -56,9 +56,11 @@ class AppDelegateReducer: ReducerType {
mainWindow.htmlPreview = HtmlPreviewState(
htmlFile: nil,
server: Marked(self.baseServerUrl.appendingPathComponent(HtmlPreviewToolReducer.selectFirstPath))
server: Marked(
HtmlPreviewReducer.serverUrl(baseUrl: self.baseServerUrl, uuid: mainWindow.uuid)
)
)
mainWindow.preview.server = self.baseServerUrl.appendingPathComponent(MarkdownReducer.nonePath)
mainWindow.preview.server = nil
mainWindow.usesVcsIgnores = state.openQuickly.defaultUsesVcsIgnores
mainWindow.nvimArgs = config.nvimArgs

View File

@ -29,7 +29,28 @@ extension NSColor {
}
}
var hex: String { String(format: "%X", self.int) }
var hex: String { String(String(format: "%06X", self.int).suffix(6)) }
convenience init(rgb: Int) {
// @formatter:off
let red = ((rgb >> 16) & 0xFF).cgf / 255.0;
let green = ((rgb >> 8) & 0xFF).cgf / 255.0;
let blue = ((rgb ) & 0xFF).cgf / 255.0;
// @formatter:on
self.init(srgbRed: red, green: green, blue: blue, alpha: 1.0)
}
convenience init?(hex: String) {
var result: UInt32 = 0
guard hex.count == 6, Scanner(string: hex).scanHexInt32(&result) else { return nil }
let r = (result & 0xFF0000) >> 16
let g = (result & 0x00FF00) >> 8
let b = (result & 0x0000FF)
self.init(srgbRed: r.cgf / 255, green: g.cgf / 255, blue: b.cgf / 255, alpha: 1)
}
func brightening(by factor: CGFloat) -> NSColor {
guard let color = self.usingColorSpace(.sRGB) else { return self }

View File

@ -19,6 +19,7 @@ class ConditionVariable {
while !self.posted {
self.condition.wait(until: Date(timeIntervalSinceNow: seconds))
self.posted = true
}
fn?()

View File

@ -21,8 +21,9 @@ class Context: ReduxContext {
init(baseServerUrl: URL, state: AppState) {
super.init(initialState: state)
let previewMiddleware = PreviewMiddleware()
let markdownReducer = MarkdownReducer(baseServerUrl: baseServerUrl)
let markdownPreviewMiddleware = MarkdownPreviewMiddleware()
let markdownPreviewReducer = MarkdownPreviewReducer(baseServerUrl: baseServerUrl)
let htmlPreviewReducer = HtmlPreviewReducer(baseServerUrl: baseServerUrl)
let httpMiddleware: HttpServerMiddleware = HttpServerMiddleware(port: baseServerUrl.port!)
let uiRootReducer = UiRootReducer()
let openQuicklyReducer = OpenQuicklyReducer()
@ -68,19 +69,22 @@ class Context: ReduxContext {
.reduce(
by: [
MainWindowReducer().reduce,
markdownReducer.mainWindow.reduce,
markdownReducer.previewTool.reduce,
PreviewToolReducer(baseServerUrl: baseServerUrl).reduce,
HtmlPreviewToolReducer(baseServerUrl: baseServerUrl).reduce,
markdownPreviewReducer.mainWindow.reduce,
markdownPreviewReducer.previewTool.reduce,
MarkdownToolReducer(baseServerUrl: baseServerUrl).reduce,
htmlPreviewReducer.mainWindow.reduce,
htmlPreviewReducer.htmlPreview.reduce,
FileBrowserReducer().reduce,
BuffersListReducer().reduce,
markdownReducer.buffersList.reduce,
markdownPreviewReducer.buffersList.reduce,
],
middlewares: [
previewMiddleware.mainWindow.apply,
httpMiddleware.mainWindow.apply,
previewMiddleware.previewTool.apply,
httpMiddleware.htmlPreview.apply,
markdownPreviewMiddleware.mainWindow.apply,
httpMiddleware.markdownPreview.apply,
markdownPreviewMiddleware.markdownTool.apply,
HtmlPreviewMiddleware().apply,
httpMiddleware.htmlPreviewMainWindow.apply,
httpMiddleware.htmlPreviewTool.apply,
]
)
.filter { $0.modified }

38
VimR/VimR/CssUtils.swift Normal file
View File

@ -0,0 +1,38 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class CssUtils {
static let cssOverridesTemplate: String = try! String(
contentsOf: Resources.cssOverridesTemplateUrl
)
static func cssOverrides(with theme: Theme) -> String {
self
.cssOverridesTemplate
.replacingOccurrences(of: "{{ nvim-color }}", with: self.htmlColor(theme.cssColor))
.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-h6-color }}", with: self.htmlColor(theme.cssH6Color))
.replacingOccurrences(of: "{{ nvim-code-background-color }}",
with: self.htmlColor(theme.cssCodeBackgroundColor))
.replacingOccurrences(of: "{{ nvim-code-color }}", with: self.htmlColor(theme.cssCodeColor))
}
private static func htmlColor(_ color: NSColor) -> String { "#\(color.hex)" }
}

View File

@ -8,13 +8,13 @@ import WebKit
struct Defs {
static let loggerSubsystem = "com.qvacua.VimR"
static let loggerSubsystem = Bundle.main.bundleIdentifier!
struct LoggerCategory {
static let general = "general"
static let uiComponents = "ui-components"
static let ui = "ui"
static let middleware = "middleware"
static let service = "service"
}

View File

@ -183,7 +183,7 @@ class FileOutlineView: NSOutlineView,
private var triangleOpen: NSImage
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.uiComponents)
category: Defs.LoggerCategory.ui)
private func initContextMenu() {
// Loading the nib file will set self.menu.

View File

@ -25,7 +25,9 @@ class FileUtils {
private static let fileManager = FileManager.default
static let userHomeUrl = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
static func tempDir() -> URL { URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) }
static func directDescendants(of url: URL) -> [URL] {
guard let childUrls = try? self.fileManager.contentsOfDirectory(
at: url, includingPropertiesForKeys: self.keysToGet, options: self.scanOptions

View File

@ -0,0 +1,52 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class HtmlPreviewMiddleware: MiddlewareType {
static func selectFirstHtmlUrl(uuid: UUID) -> URL {
FileUtils.tempDir().appendingPathComponent("\(uuid)-select-first.html")
}
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
init() {
self.selectFirstHtmlTemplate = try! String(contentsOf: Resources.selectFirstHtmlTemplateUrl)
}
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
{ tuple in
let result = reduce(tuple)
if tuple.state.appearance.theme.mark != self.themeToken {
self.updateCssOverrides(with: tuple.state.appearance.theme.payload)
self.themeToken = tuple.state.appearance.theme.mark
}
self.updateCssOverrides(with: tuple.state.appearance.theme.payload)
self.writeSelectFirstHtml(uuid: tuple.state.uuid)
return result
}
}
private func writeSelectFirstHtml(uuid: UUID) {
let url = HtmlPreviewMiddleware.selectFirstHtmlUrl(uuid: uuid)
try? self.selectFirstHtml.write(to: url, atomically: true, encoding: .utf8)
}
private func updateCssOverrides(with theme: Theme) {
self.selectFirstHtml = self
.selectFirstHtmlTemplate
.replacingOccurrences(of: "{{ css-overrides }}", with: CssUtils.cssOverrides(with: theme))
}
private var themeToken = Token()
private var selectFirstHtml = ""
private let selectFirstHtmlTemplate: String
}

View File

@ -47,18 +47,19 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
if state.viewToBeFocused != nil,
case .htmlPreview = state.viewToBeFocused! {
self.beFirstResponder()
}
case .htmlPreview = state.viewToBeFocused! { self.beFirstResponder() }
guard let serverUrl = state.htmlPreview.server, let htmlFileUrl = state.htmlPreview.htmlFile else {
guard let serverUrl = state.htmlPreview.server else {
self.monitor = nil
return
}
if serverUrl.mark == self.mark {
return
}
if serverUrl.mark == self.mark { return }
self.mark = serverUrl.mark
self.reloadWebview(with: serverUrl.payload)
guard let htmlFileUrl = state.htmlPreview.htmlFile else { return }
do {
self.monitor = try EonilFSEventStream(
@ -67,19 +68,16 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
latency: fileSystemEventsLatency,
flags: [.fileEvents],
handler: { [weak self] event in
Swift.print(event)
self?.reloadWebview(with: serverUrl.payload)
})
self.monitor?.setDispatchQueue(monitorDispatchQueue)
try self.monitor?.start()
} catch {
self.log.error("Could not start file monitor for \(htmlFileUrl): "
+ "\(error)")
self.log.error("Could not start file monitor for \(htmlFileUrl): \(error)")
}
self.innerCustomToolbar.selectHtmlFile.toolTip = (htmlFileUrl.path as NSString).abbreviatingWithTildeInPath
self.mark = serverUrl.mark
self.reloadWebview(with: serverUrl.payload)
self.innerCustomToolbar
.selectHtmlFile.toolTip = (htmlFileUrl.path as NSString).abbreviatingWithTildeInPath
})
.disposed(by: self.disposeBag)
}
@ -117,25 +115,19 @@ class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
private let disposeBag = DisposeBag()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.uiComponents)
category: Defs.LoggerCategory.ui)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@objc func selectHtmlFile(sender: Any?) {
let panel = NSOpenPanel()
panel.canChooseDirectories = false
panel.allowsMultipleSelection = false
panel.beginSheetModal(for: self.window!) { result in
guard result == .OK else {
return
}
guard result == .OK else { return }
let urls = panel.urls
guard urls.count == 1 else {
return
}
guard urls.count == 1 else { return }
self.emit(UuidAction(uuid: self.uuid, action: .selectHtmlFile(urls[0])))
}
@ -151,9 +143,7 @@ extension HtmlPreviewTool {
class InnerCustomToolbar: CustomToolBar {
fileprivate weak var htmlPreviewTool: HtmlPreviewTool? {
didSet {
self.selectHtmlFile.target = self.htmlPreviewTool
}
didSet { self.selectHtmlFile.target = self.htmlPreviewTool }
}
let selectHtmlFile = NSButton(forAutoLayout: ())
@ -187,12 +177,9 @@ extension HtmlPreviewTool {
self.addSubview(selectHtmlFile)
selectHtmlFile.autoPinEdge(toSuperviewEdge: .top)
selectHtmlFile.autoPinEdge(toSuperviewEdge: .right,
withInset: InnerToolBar.itemPadding)
selectHtmlFile.autoPinEdge(toSuperviewEdge: .right, withInset: InnerToolBar.itemPadding)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
}

View File

@ -5,34 +5,73 @@
import Foundation
class HtmlPreviewToolReducer: ReducerType {
class HtmlPreviewReducer {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<HtmlPreviewTool.Action>
static let basePath = "tools/html-preview"
static let basePath = "/tools/html-preview"
static let selectFirstPath = "/tools/html-preview/select-first.html"
static func serverUrl(baseUrl: URL, uuid: UUID) -> URL {
baseUrl.appendingPathComponent("\(uuid)/\(basePath)/index.html")
}
let mainWindow: MainWindowReducer
let htmlPreview: HtmlPreviewToolReducer
init(baseServerUrl: URL) {
self.baseServerUrl = baseServerUrl
self.mainWindow = MainWindowReducer(baseServerUrl: baseServerUrl)
self.htmlPreview = HtmlPreviewToolReducer(baseServerUrl: baseServerUrl)
}
func typedReduce(_ pair: ReduceTuple) -> ReduceTuple {
var state = pair.state
let uuid = pair.action.uuid
class MainWindowReducer: ReducerType {
switch pair.action.payload {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
case let .selectHtmlFile(url):
state.htmlPreview.htmlFile = url
state.htmlPreview.server = Marked(
self.baseServerUrl.appendingPathComponent("\(uuid)/\(HtmlPreviewToolReducer.basePath)/index.html")
)
init(baseServerUrl: URL) { self.baseServerUrl = baseServerUrl }
func typedReduce(_ pair: ReduceTuple) -> ReduceTuple {
var state = pair.state
switch pair.action.payload {
case .setTheme:
guard state.htmlPreview.htmlFile == nil else { return pair }
state.htmlPreview.server = Marked(
HtmlPreviewReducer.serverUrl(baseUrl: self.baseServerUrl, uuid: state.uuid)
)
default:
return pair
}
return (state, pair.action, true)
}
return (state, pair.action, true)
private let baseServerUrl: URL
}
private let baseServerUrl: URL
class HtmlPreviewToolReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<HtmlPreviewTool.Action>
init(baseServerUrl: URL) { self.baseServerUrl = baseServerUrl }
func typedReduce(_ pair: ReduceTuple) -> ReduceTuple {
var state = pair.state
switch pair.action.payload {
case .selectHtmlFile(let url):
state.htmlPreview.htmlFile = url
state.htmlPreview.server = Marked(
HtmlPreviewReducer.serverUrl(baseUrl: self.baseServerUrl, uuid: state.uuid)
)
}
return (state, pair.action, true)
}
private let baseServerUrl: URL
}
}

View File

@ -9,30 +9,55 @@ import os
class HttpServerMiddleware {
let htmlPreview: HtmlPreviewMiddleware
let mainWindow: MainWindowMiddleware
let htmlPreviewTool: HtmlPreviewToolMiddleware
let htmlPreviewMainWindow: HtmlPreviewMainWindowMiddleware
let markdownPreview: MarkdownPreviewMiddleware
init(port: Int) {
let localhost = "127.0.0.1"
// We know that the URL is valid!
let baseUrl = URL(string: "http://\(localhost):\(port)")!
let cssOverridesTemplate = try! String(contentsOf: Resources.cssOverridesTemplateUrl)
let selectFirstHtmlTemplate = try! String(contentsOf: Resources.selectFirstHtmlTemplateUrl)
let server = HttpServer()
server.listenAddressIPv4 = "127.0.0.1"
server.listenAddressIPv4 = localhost
let resourceUrl = Bundle.main.resourceURL!
let githubCssUrl = resourceUrl.appendingPathComponent("markdown/github-markdown.css")
self.htmlPreview = HtmlPreviewMiddleware(server: server, githubCssUrl: githubCssUrl)
self.mainWindow = MainWindowMiddleware(server: server, githubCssUrl: githubCssUrl)
let htmlTemplates = (
selectFirst: selectFirstHtmlTemplate,
cssOverrides: cssOverridesTemplate
)
self.htmlPreviewTool = HtmlPreviewToolMiddleware(
server: server,
baseUrl: baseUrl,
cssUrl: Resources.cssUrl,
htmlTemplates: htmlTemplates
)
self.htmlPreviewMainWindow = HtmlPreviewMainWindowMiddleware(
server: server,
baseUrl: baseUrl,
cssUrl: Resources.cssUrl,
htmlTemplates: htmlTemplates
)
self.markdownPreview = MarkdownPreviewMiddleware(
server: server,
baseUrl: baseUrl,
cssUrl: Resources.cssUrl,
baseCssUrl: Resources.baseCssUrl
)
do {
try server.start(in_port_t(port), forceIPv4: true)
self.log.info("VimR http server started on http://localhost:\(port)")
self.log.info("VimR http server started on \(baseUrl)")
let previewResourceUrl = resourceUrl.appendingPathComponent("preview")
server["\(MarkdownReducer.basePath)/:path"] = shareFilesFromDirectory(previewResourceUrl.path)
server.GET["\(MarkdownReducer.basePath)/github-markdown.css"] = shareFile(githubCssUrl.path)
server["\(HtmlPreviewToolReducer.basePath)/:path"] = shareFilesFromDirectory(previewResourceUrl.path)
server.GET["\(HtmlPreviewToolReducer.basePath)/github-markdown.css"] = shareFile(githubCssUrl.path)
// server["\(HtmlPreviewToolReducer.basePath)/:path"] = shareFilesFromDirectory(
// Resources.previewUrl.path
// )
// server.GET["\(HtmlPreviewToolReducer.basePath)/github-markdown.css"] = shareFile(
// Resources.cssUrl.path
// )
} catch {
self.log.error("Server could not be started on port \(port): \(error)")
}
@ -41,89 +66,161 @@ class HttpServerMiddleware {
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
class HtmlPreviewMiddleware: MiddlewareType {
class HtmlPreviewMainWindowMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
fileprivate init(server: HttpServer, baseUrl: URL, cssUrl: URL, htmlTemplates: HtmlTemplates) {
self.server = server
self.baseUrl = baseUrl
self.cssUrl = cssUrl
}
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
{ tuple in
let result = reduce(tuple)
guard case .setTheme = tuple.action.payload else { return result }
let state = result.state
guard state.htmlPreview.htmlFile == nil,
let serverUrl = state.htmlPreview.server else { return result }
let basePath = serverUrl.payload.deletingLastPathComponent()
self.server.GET[basePath.appendingPathComponent("github-markdown.css").path] = shareFile(
Resources.cssUrl.path
)
self.server.GET[basePath.appendingPathComponent("base.css").path] = shareFile(
Resources.baseCssUrl.path
)
self.server.GET[serverUrl.payload.path] = shareFile(
HtmlPreviewMiddleware.selectFirstHtmlUrl(uuid: state.uuid).path
)
self.log.info("Serving on \(self.fullUrl(with: serverUrl.payload.path)) the select first")
return result
}
}
private let server: HttpServer
private let baseUrl: URL
private let cssUrl: URL
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>
init(server: HttpServer, githubCssUrl: URL) {
fileprivate init(server: HttpServer, baseUrl: URL, cssUrl: URL, htmlTemplates: HtmlTemplates) {
self.server = server
self.githubCssUrl = githubCssUrl
self.baseUrl = baseUrl
self.cssUrl = cssUrl
}
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
return { tuple in
{ tuple in
let result = reduce(tuple)
guard case .selectHtmlFile = tuple.action.payload else {
return result
}
guard case .selectHtmlFile = tuple.action.payload else { return result }
let state = result.state
guard let serverUrl = state.htmlPreview.server, let htmlFileUrl = state.htmlPreview.htmlFile else {
return result
}
guard let serverUrl = state.htmlPreview.server,
let htmlFileUrl = state.htmlPreview.htmlFile else { return result }
self.log.debug("Serving \(htmlFileUrl) on \(serverUrl)")
let basePath = serverUrl.payload.deletingLastPathComponent().path
self.server.GET[serverUrl.payload.path] = shareFile(htmlFileUrl.path)
self.server["\(basePath)/:path"] = shareFilesFromDirectory(htmlFileUrl.parent.path)
self.log.info(
"Serving on \(self.fullUrl(with: serverUrl.payload.path)) the HTML file \(htmlFileUrl)"
)
return result
}
}
private let server: HttpServer
private let githubCssUrl: URL
private let baseUrl: URL
private let cssUrl: URL
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private func fullUrl(with path: String) -> URL { self.baseUrl.appendingPathComponent(path) }
}
class MainWindowMiddleware: MiddlewareType {
class MarkdownPreviewMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
init(server: HttpServer, githubCssUrl: URL) {
fileprivate init(server: HttpServer, baseUrl: URL, cssUrl: URL, baseCssUrl: URL) {
self.server = server
self.githubCssUrl = githubCssUrl
self.baseUrl = baseUrl
self.cssUrl = cssUrl
self.baseCssUrl = baseCssUrl
}
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
return { tuple in
{ tuple in
let result = reduce(tuple)
let uuidAction = tuple.action
guard case .newCurrentBuffer = uuidAction.payload else {
switch uuidAction.payload {
case .newCurrentBuffer: fallthrough
case .bufferWritten: fallthrough
case .setTheme:
break
default:
return result
}
let preview = result.state.preview
guard case .markdown = preview.status,
let buffer = preview.buffer,
let html = preview.html,
let server = preview.server else {
guard let htmlUrl = preview.html,
let serverUrl = preview.server else { return result }
return result
self.log.debug("Serving \(htmlUrl) on \(serverUrl)")
let htmlBasePath = serverUrl.deletingLastPathComponent().path
if let bufferUrl = preview.buffer {
self.server["\(htmlBasePath)/:path"] = shareFilesFromDirectory(
bufferUrl.deletingLastPathComponent().path
)
}
self.log.debug("Serving \(html) on \(server)")
let htmlBasePath = server.deletingLastPathComponent().path
self.server.GET[serverUrl.path] = shareFile(htmlUrl.path)
self.server.GET["\(htmlBasePath)/github-markdown.css"] = shareFile(self.cssUrl.path)
self.server.GET["\(htmlBasePath)/base.css"] = shareFile(self.baseCssUrl.path)
self.server["\(htmlBasePath)/:path"] = shareFilesFromDirectory(buffer.deletingLastPathComponent().path)
self.server.GET[server.path] = shareFile(html.path)
self.server.GET["\(htmlBasePath)/github-markdown.css"] = shareFile(self.githubCssUrl.path)
self.log.info("Serving on \(self.fullUrl(with: serverUrl.path)) for markdown preview")
return result
}
}
private let server: HttpServer
private let githubCssUrl: URL
private let baseUrl: URL
private let cssUrl: URL
private let baseCssUrl: URL
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private func fullUrl(with path: String) -> URL { self.baseUrl.appendingPathComponent(path) }
}
}
private typealias HtmlTemplates = (
selectFirst: String,
cssOverrides: String
)

View File

@ -1224,7 +1224,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.32.0</string>
<string>SNAPSHOT-347</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@ -1241,7 +1241,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>344</string>
<string>347</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.productivity</string>
<key>LSMinimumSystemVersion</key>

View File

@ -85,8 +85,15 @@ extension MainWindow {
.disposed(by: self.disposeBag)
}
func colorschemeChanged(to neoVimTheme: NvimView.Theme) {
self.emit(uuidAction(for: .setTheme(Theme(neoVimTheme))))
func colorschemeChanged(to nvimTheme: NvimView.Theme) {
self
.updateCssColors()
.subscribe(onSuccess: { colors in
self.emit(self.uuidAction(
for: .setTheme(Theme(from: nvimTheme, additionalColorDict: colors)))
)
})
.disposed(by: self.disposeBag)
}
func ipcBecameInvalid(reason: String) {
@ -113,6 +120,42 @@ extension MainWindow {
self.editorPosition = Marked(position)
self.cursorDebouncer.call(.setCursor(to: self.editorPosition))
}
private func updateCssColors() -> Single<[String: CellAttributes]> {
let colorNames = [
"Normal", // color and background-color
"Directory", // a
"Question", // blockquote foreground
"CursorColumn", // code background and foreground
]
typealias HlResult = Dictionary<String, RxNeovimApi.Value>
typealias ColorNameHlResultTuple = (colorName: String, hlResult: HlResult)
typealias ColorNameObservableTuple = (colorName: String, observable: Observable<HlResult>)
return Observable
.from(colorNames.map { colorName -> ColorNameObservableTuple in
(
colorName: colorName,
observable: self.neoVimView.api
.getHlByName(name: colorName, rgb: true)
.asObservable()
)
})
.flatMap { tuple -> Observable<(String, HlResult)> in
Observable.zip(Observable.just(tuple.colorName), tuple.observable)
}
.reduce([ColorNameHlResultTuple]()) { (result, element: ColorNameHlResultTuple) in
result + [element]
}
.map { (array: [ColorNameHlResultTuple]) in
Dictionary(uniqueKeysWithValues: array)
.mapValues { value in
CellAttributes(withDict: value, with: self.neoVimView.defaultCellAttributes)
}
}
.asSingle()
}
}
// MARK: - NSWindowDelegate

View File

@ -84,7 +84,7 @@ class MainWindow: NSObject,
var tools: [Tools: WorkspaceTool] = [:]
if state.activeTools[.preview] == true {
self.preview = PreviewTool(source: source, emitter: emitter, state: state)
self.preview = MarkdownTool(source: source, emitter: emitter, state: state)
let previewConfig = WorkspaceTool.Config(
title: "Markdown",
view: self.preview!,
@ -237,7 +237,7 @@ class MainWindow: NSObject,
private var previewPosition = Marked(Position.beginning)
private var preview: PreviewTool?
private var preview: MarkdownTool?
private var htmlPreview: HtmlPreviewTool?
private var fileBrowser: FileBrowser?
private var buffersList: BuffersList?
@ -246,7 +246,7 @@ class MainWindow: NSObject,
private var lastThemeMark = Token()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.uiComponents)
category: Defs.LoggerCategory.ui)
private func setupScrollAndCursorDebouncers() {
Observable

View File

@ -0,0 +1,185 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import CocoaMarkdown
import os
class MarkdownPreviewMiddleware {
let markdownTool: MarkdownToolMiddleware
let mainWindow: MainWindowMiddleware
init() {
let generator = PreviewGenerator()
self.markdownTool = MarkdownToolMiddleware(generator: generator)
self.mainWindow = MainWindowMiddleware(generator: generator)
}
class PreviewGenerator {
init() {
// We know that the files are there!
self.template = try! String(contentsOf: Resources.markdownTemplateUrl)
self.emptyHtmlTemplate = try! String(contentsOf: Resources.emptyHtmlTemplateUrl)
self.errorHtmlTemplate = try! String(contentsOf: Resources.errorHtmlTemplateUrl)
self.saveFirstHtmlTemplate = try! String(contentsOf: Resources.saveFirstHtmlTemplateUrl)
self.updateCssOverrides(with: Theme.default)
}
func apply(_ state: MainWindow.State, uuid: UUID) {
let preview = state.preview
if state.appearance.theme.mark != self.themeToken {
self.updateCssOverrides(with: state.appearance.theme.payload)
self.themeToken = state.appearance.theme.mark
}
self.removePreviewHtmlFile(uuid: uuid)
guard let htmlUrl = preview.html else {return }
switch preview.status {
case .none:
self.writePage(html: self.emptyHtml, uuid: uuid, url: htmlUrl)
case .notSaved:
self.writePage(html: self.saveFirstHtml, uuid: uuid, url: htmlUrl)
case .error:
self.writePage(html: self.errorHtml, uuid: uuid, url: htmlUrl)
case .markdown:
guard let buffer = preview.buffer else { return }
do {
try self.render(buffer, to: htmlUrl)
self.previewFiles[uuid] = htmlUrl
} catch let error as NSError {
// FIXME: error handling!
self.log.error("error while rendering \(buffer) to \(htmlUrl): \(error)")
return
}
}
}
private func writePage(html: String, uuid: UUID, url: URL) {
try? html.write(to: url, atomically: true, encoding: .utf8)
self.previewFiles[uuid] = url
}
private func removePreviewHtmlFile(uuid: UUID) {
guard let previewUrl = self.previewFiles[uuid] else { return }
try? FileManager.default.removeItem(at: previewUrl)
self.previewFiles.removeValue(forKey: uuid)
}
private func updateCssOverrides(with theme: Theme) {
self.cssOverrides = CssUtils.cssOverrides(with: theme)
self.emptyHtml = self.fillCssOverrides(template: self.emptyHtmlTemplate)
self.errorHtml = self.fillCssOverrides(template: self.errorHtmlTemplate)
self.saveFirstHtml = self.fillCssOverrides(template: self.saveFirstHtmlTemplate)
}
private var themeToken = Token()
private var cssOverrides = ""
private var emptyHtml = ""
private var errorHtml = ""
private var saveFirstHtml = ""
private let emptyHtmlTemplate: String
private let errorHtmlTemplate: String
private let saveFirstHtmlTemplate: String
private let template: String
private var previewFiles = [UUID: URL]()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private func render(_ bufferUrl: URL, to htmlUrl: URL) throws {
let doc = CMDocument(contentsOfFile: bufferUrl.path, options: .sourcepos)
let renderer = CMHTMLRenderer(document: doc)
guard let body = renderer?.render() else {
// FIXME: error handling!
return
}
let html = filledTemplate(body: body, title: bufferUrl.lastPathComponent)
let htmlFilePath = htmlUrl.path
try html.write(toFile: htmlFilePath, atomically: true, encoding: .utf8)
}
private func fillCssOverrides(template: String) -> String {
template.replacingOccurrences(of: "{{ css-overrides }}", with: self.cssOverrides)
}
private func filledTemplate(body: String, title: String) -> String {
self.template
.replacingOccurrences(of: "{{ title }}", with: title)
.replacingOccurrences(of: "{{ body }}", with: body)
.replacingOccurrences(of: "{{ css-overrides }}", with: self.cssOverrides)
}
}
class MarkdownToolMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MarkdownTool.Action>
init(generator: PreviewGenerator) { self.generator = generator }
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
{ tuple in
let result = reduce(tuple)
let uuidAction = tuple.action
guard case .refreshNow = 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
typealias ActionType = UuidAction<MainWindow.Action>
init(generator: PreviewGenerator) { self.generator = generator }
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
{ tuple in
let result = reduce(tuple)
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
}
}
private let generator: PreviewGenerator
}
}

View File

@ -0,0 +1,222 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class MarkdownPreviewReducer {
static private func previewState(
for uuid: UUID,
baseUrl: URL,
buffer: NvimView.Buffer?,
editorPosition: Marked<Position>,
previewPosition: Marked<Position>
) -> PreviewState {
var state = PreviewState(
html: self.htmlUrl(with: uuid),
server: self.serverUrl(for: uuid, baseUrl: baseUrl, lastComponent: indexHtml),
editorPosition: editorPosition,
previewPosition: previewPosition
)
state.status = .notSaved
guard let url = buffer?.url else { return state }
state.status = .error
guard FileUtils.fileExists(at: url) else { return state }
state.status = .none
guard self.extensions.contains(url.pathExtension) else { return state }
state.status = .markdown
state.buffer = url
return state
}
private static func serverUrl(for uuid: UUID, baseUrl: URL, lastComponent: String) -> URL {
baseUrl.appendingPathComponent("\(uuid)/tools/markdown/\(lastComponent)")
}
private static func htmlUrl(with uuid: UUID) -> URL {
FileUtils.tempDir().appendingPathComponent("\(uuid)-markdown-index.html")
}
private static let extensions = Set(["md", "markdown", "mdown", "mkdn", "mkd"])
let previewTool: PreviewToolReducer
let buffersList: BuffersListReducer
let mainWindow: MainWindowReducer
init(baseServerUrl: URL) {
self.previewTool = PreviewToolReducer(baseServerUrl: baseServerUrl)
self.buffersList = BuffersListReducer(baseServerUrl: baseServerUrl)
self.mainWindow = MainWindowReducer(baseServerUrl: baseServerUrl)
}
class PreviewToolReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MarkdownTool.Action>
func typedReduce(_ tuple: ReduceTuple) -> ReduceTuple {
var state = tuple.state
switch tuple.action.payload {
case .refreshNow:
state.preview = MarkdownPreviewReducer.previewState(
for: tuple.state.uuid,
baseUrl: self.baseServerUrl,
buffer: state.currentBuffer,
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition
)
state.preview.lastSearch = .reload
case let .reverseSearch(to:position):
state.preview.previewPosition = Marked(position)
state.preview.lastSearch = .reverse
case let .scroll(to:position):
if state.preview.lastSearch == .reload {
state.preview.lastSearch = .none
break;
}
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(position)
state.preview.lastSearch = .reverse
default:
return tuple
}
return (state, tuple.action, true)
}
init(baseServerUrl: URL) { self.baseServerUrl = baseServerUrl }
private let baseServerUrl: URL
}
class BuffersListReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<BuffersList.Action>
func typedReduce(_ tuple: ReduceTuple) -> ReduceTuple {
var state = tuple.state
switch tuple.action.payload {
case let .open(buffer):
state.preview = MarkdownPreviewReducer.previewState(
for: tuple.state.uuid,
baseUrl: self.baseServerUrl,
buffer: buffer,
editorPosition: Marked(.beginning),
previewPosition: Marked(.beginning)
)
state.preview.lastSearch = .none
}
return (state, tuple.action, true)
}
init(baseServerUrl: URL) { self.baseServerUrl = baseServerUrl }
private let baseServerUrl: URL
}
class MainWindowReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
func typedReduce(_ tuple: ReduceTuple) -> ReduceTuple {
var state = tuple.state
switch tuple.action.payload {
case let .newCurrentBuffer(buffer):
state.preview = MarkdownPreviewReducer.previewState(
for: tuple.state.uuid,
baseUrl: self.baseServerUrl,
buffer: buffer,
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition
)
state.preview.lastSearch = .none
case .bufferWritten:
state.preview = MarkdownPreviewReducer.previewState(
for: tuple.state.uuid,
baseUrl: self.baseServerUrl,
buffer: state.currentBuffer,
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition
)
state.preview.lastSearch = .reload
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.editorPosition = Marked(
mark: state.preview.editorPosition.mark,
payload: position.payload
)
state.preview.lastSearch = .none
break
}
state.preview.editorPosition = Marked(position.payload)
// .none because the forward search does not invoke .scroll above.
state.preview.lastSearch = .none
case .close:
state.preview = self.stateForClose(state)
state.preview.lastSearch = .none
default:
return tuple
}
return (state, tuple.action, true)
}
init(baseServerUrl: URL) { self.baseServerUrl = baseServerUrl }
private func stateForClose(_ state: StateType) -> PreviewState {
PreviewState(
status: .none,
html: MarkdownPreviewReducer.htmlUrl(with: state.uuid),
server: MarkdownPreviewReducer.serverUrl(
for: state.uuid,
baseUrl: self.baseServerUrl,
lastComponent: indexHtml
),
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition
)
}
private let baseServerUrl: URL
}
}
private let indexHtml = "index.html"

View File

@ -9,7 +9,7 @@ import PureLayout
import WebKit
import os
class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
class MarkdownTool: NSView, UiComponent, WKNavigationDelegate {
enum Action {
@ -63,21 +63,21 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
self.configureForAutoLayout()
refreshMenuItem.target = self
refreshMenuItem.action = #selector(PreviewTool.refreshNowAction)
refreshMenuItem.action = #selector(MarkdownTool.refreshNowAction)
forwardSearchMenuItem.target = self
forwardSearchMenuItem.action = #selector(PreviewTool.forwardSearchAction)
forwardSearchMenuItem.action = #selector(MarkdownTool.forwardSearchAction)
reverseSearchMenuItem.target = self
reverseSearchMenuItem.action = #selector(PreviewTool.reverseSearchAction)
reverseSearchMenuItem.action = #selector(MarkdownTool.reverseSearchAction)
automaticForward.target = self
automaticForward.action = #selector(PreviewTool.automaticForwardSearchAction)
automaticForward.action = #selector(MarkdownTool.automaticForwardSearchAction)
automaticReverse.target = self
automaticReverse.action = #selector(PreviewTool.automaticReverseSearchAction)
automaticReverse.action = #selector(MarkdownTool.automaticReverseSearchAction)
refreshOnWrite.target = self
refreshOnWrite.action = #selector(PreviewTool.refreshOnWriteAction)
refreshOnWrite.action = #selector(MarkdownTool.refreshOnWriteAction)
self.addViews()
self.webview.navigationDelegate = self
self.webview.load(URLRequest(url: state.preview.server!))
if let url = state.preview.server { self.webview.load(URLRequest(url: url)) }
source
.observeOn(MainScheduler.instance)
@ -173,7 +173,7 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
private let refreshOnWriteMenuItem = NSMenuItem(title: "Refresh on Write", action: nil, keyEquivalent: "")
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.uiComponents)
category: Defs.LoggerCategory.ui)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
@ -189,7 +189,7 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
}
// MARK: - Actions
extension PreviewTool {
extension MarkdownTool {
@objc func refreshNowAction(_: Any?) {
self.emit(UuidAction(uuid: self.uuid, action: .refreshNow))

View File

@ -5,10 +5,10 @@
import Foundation
class PreviewToolReducer: ReducerType {
class MarkdownToolReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<PreviewTool.Action>
typealias ActionType = UuidAction<MarkdownTool.Action>
init(baseServerUrl: URL) {
self.baseServerUrl = baseServerUrl

View File

@ -83,7 +83,7 @@ class OpenQuicklyWindow: NSObject,
private let fileView = NSTableView.standardTableView()
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.uiComponents)
category: Defs.LoggerCategory.ui)
private var window: NSWindow { self.windowController.window! }

View File

@ -1,148 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import CocoaMarkdown
import os
class PreviewMiddleware {
let previewTool: PreviewToolMiddleware
let mainWindow: MainWindowMiddleware
init() {
let generator = PreviewGenerator()
self.previewTool = PreviewToolMiddleware(generator: generator)
self.mainWindow = MainWindowMiddleware(generator: generator)
}
class PreviewGenerator {
init() {
guard let templateUrl = Bundle.main.url(forResource: "template",
withExtension: "html",
subdirectory: "markdown")
else {
preconditionFailure("ERROR Cannot load markdown template")
}
guard let template = try? String(contentsOf: templateUrl) else {
preconditionFailure("ERROR Cannot load markdown template")
}
self.template = template
}
func apply(_ state: MainWindow.State, uuid: UUID) {
let preview = state.preview
guard let buffer = preview.buffer, let html = preview.html else {
guard let previewUrl = self.previewFiles[uuid] else {
return
}
try? FileManager.default.removeItem(at: previewUrl)
self.previewFiles.removeValue(forKey: uuid)
return
}
do {
try self.render(buffer, to: html)
self.previewFiles[uuid] = html
} catch let error as NSError {
// FIXME: error handling!
self.log.error("error whilte rendering \(buffer) to \(html): \(error)")
return
}
}
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.middleware)
private func render(_ bufferUrl: URL, to htmlUrl: URL) throws {
let doc = CMDocument(contentsOfFile: bufferUrl.path, options: .sourcepos)
let renderer = CMHTMLRenderer(document: doc)
guard let body = renderer?.render() else {
// FIXME: error handling!
return
}
let html = filledTemplate(body: body, title: bufferUrl.lastPathComponent)
let htmlFilePath = htmlUrl.path
try html.write(toFile: htmlFilePath, atomically: true, encoding: .utf8)
}
private func filledTemplate(body: String, title: String) -> String {
return self.template
.replacingOccurrences(of: "{{ title }}", with: title)
.replacingOccurrences(of: "{{ body }}", with: body)
}
private let template: String
private var previewFiles = [UUID: URL]()
}
class PreviewToolMiddleware: MiddlewareType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<PreviewTool.Action>
init(generator: PreviewGenerator) {
self.generator = generator
}
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
return { tuple in
let result = reduce(tuple)
let uuidAction = tuple.action
guard case .refreshNow = 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
typealias ActionType = UuidAction<MainWindow.Action>
init(generator: PreviewGenerator) {
self.generator = generator
}
func typedApply(_ reduce: @escaping TypedActionReduceFunction) -> TypedActionReduceFunction {
return { tuple in
let result = reduce(tuple)
let uuidAction = tuple.action
switch uuidAction.payload {
case .newCurrentBuffer:
self.generator.apply(result.state, uuid: uuidAction.uuid)
case .bufferWritten:
self.generator.apply(result.state, uuid: uuidAction.uuid)
default:
return result
}
return result
}
}
private let generator: PreviewGenerator
}
}

View File

@ -1,166 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class MarkdownReducer {
static let basePath = "/tools/markdown"
static let saveFirstPath = "/tools/markdown/save-first.html"
static let errorPath = "/tools/markdown/error.html"
static let nonePath = "/tools/markdown/empty.html"
let previewTool: PreviewToolReducer
let buffersList: BuffersListReducer
let mainWindow: MainWindowReducer
init(baseServerUrl: URL) {
self.previewTool = PreviewToolReducer(baseServerUrl: baseServerUrl)
self.buffersList = BuffersListReducer(baseServerUrl: baseServerUrl)
self.mainWindow = MainWindowReducer(baseServerUrl: baseServerUrl)
}
class PreviewToolReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<PreviewTool.Action>
func typedReduce(_ tuple: ReduceTuple) -> ReduceTuple {
var state = tuple.state
switch tuple.action.payload {
case .refreshNow:
state.preview = PreviewUtils.state(for: tuple.state.uuid,
baseUrl: self.baseServerUrl,
buffer: state.currentBuffer,
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition)
state.preview.lastSearch = .reload
case let .reverseSearch(to:position):
state.preview.previewPosition = Marked(position)
state.preview.lastSearch = .reverse
case let .scroll(to:position):
if state.preview.lastSearch == .reload {
state.preview.lastSearch = .none
break;
}
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(position)
state.preview.lastSearch = .reverse
default:
return tuple
}
return (state, tuple.action, true)
}
init(baseServerUrl: URL) {
self.baseServerUrl = baseServerUrl
}
private let baseServerUrl: URL
}
class BuffersListReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<BuffersList.Action>
func typedReduce(_ tuple: ReduceTuple) -> ReduceTuple {
var state = tuple.state
switch tuple.action.payload {
case let .open(buffer):
state.preview = PreviewUtils.state(for: tuple.state.uuid,
baseUrl: self.baseServerUrl,
buffer: buffer,
editorPosition: Marked(.beginning),
previewPosition: Marked(.beginning))
state.preview.lastSearch = .none
}
return (state, tuple.action, true)
}
init(baseServerUrl: URL) {
self.baseServerUrl = baseServerUrl
}
private let baseServerUrl: URL
}
class MainWindowReducer: ReducerType {
typealias StateType = MainWindow.State
typealias ActionType = UuidAction<MainWindow.Action>
func typedReduce(_ tuple: ReduceTuple) -> ReduceTuple {
var state = tuple.state
switch tuple.action.payload {
case let .newCurrentBuffer(buffer):
state.preview = PreviewUtils.state(for: tuple.state.uuid, baseUrl: self.baseServerUrl, buffer: buffer,
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition)
state.preview.lastSearch = .none
case .bufferWritten:
state.preview = PreviewUtils.state(for: tuple.state.uuid,
baseUrl: self.baseServerUrl,
buffer: state.currentBuffer,
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition)
state.preview.lastSearch = .reload
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.editorPosition = Marked(mark: state.preview.editorPosition.mark, payload: position.payload)
state.preview.lastSearch = .none
break
}
state.preview.editorPosition = Marked(position.payload)
state.preview.lastSearch = .none // .none because the forward search does not invoke .scroll above.
case .close:
state.preview = PreviewUtils.state(for: .none,
baseUrl: self.baseServerUrl,
editorPosition: state.preview.editorPosition,
previewPosition: state.preview.previewPosition)
state.preview.lastSearch = .none
default:
return tuple
}
return (state, tuple.action, true)
}
init(baseServerUrl: URL) {
self.baseServerUrl = baseServerUrl
}
private let baseServerUrl: URL
}
}

View File

@ -1,89 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
private let markdownPath = "tools/preview/markdown"
class PreviewUtils {
static func state(for status: PreviewState.Status,
baseUrl: URL,
editorPosition: Marked<Position>,
previewPosition: Marked<Position>) -> PreviewState {
switch status {
case .none:
return PreviewState(status: .none,
server: self.simpleServerUrl(with: MarkdownReducer.nonePath, baseUrl: baseUrl),
editorPosition: editorPosition,
previewPosition: previewPosition)
case .error:
return PreviewState(status: .error,
server: self.simpleServerUrl(with: MarkdownReducer.errorPath, baseUrl: baseUrl),
editorPosition: editorPosition,
previewPosition: previewPosition)
case .notSaved:
return PreviewState(status: .notSaved,
server: self.simpleServerUrl(with: MarkdownReducer.saveFirstPath, baseUrl: baseUrl),
editorPosition: editorPosition,
previewPosition: previewPosition)
case .markdown:
preconditionFailure("ERROR Use the other previewState()!")
}
}
static func state(for uuid: UUID,
baseUrl: URL,
buffer: NvimView.Buffer?,
editorPosition: Marked<Position>,
previewPosition: Marked<Position>) -> PreviewState {
guard let url = buffer?.url else {
return self.state(
for: .notSaved, baseUrl: baseUrl, editorPosition: editorPosition, previewPosition: previewPosition
)
}
guard FileUtils.fileExists(at: url) else {
return self.state(
for: .error, baseUrl: baseUrl, editorPosition: editorPosition, previewPosition: previewPosition
)
}
guard self.extensions.contains(url.pathExtension) else {
return self.state(
for: .none, baseUrl: baseUrl, editorPosition: editorPosition, previewPosition: previewPosition
)
}
return PreviewState(status: .markdown,
buffer: url,
html: self.htmlUrl(with: uuid),
server: self.serverUrl(for: uuid, baseUrl: baseUrl, lastComponent: "index.html"),
editorPosition: editorPosition,
previewPosition: previewPosition)
}
private static func serverUrl(for uuid: UUID, baseUrl: URL, lastComponent: String) -> URL {
return baseUrl.appendingPathComponent("\(uuid)/\(markdownPath)/\(lastComponent)")
}
private static func htmlUrl(with uuid: UUID) -> URL {
return self.tempDir.appendingPathComponent("\(uuid)-markdown-index.html")
}
private static func simpleServerUrl(with path: String, baseUrl: URL) -> URL {
return baseUrl.appendingPathComponent(path)
}
private static let extensions = Set(["md", "markdown"])
private static let tempDir = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
}

23
VimR/VimR/Resources.swift Normal file
View File

@ -0,0 +1,23 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class Resources {
static let resourceUrl = Bundle.main.resourceURL!
static let previewUrl = resourceUrl.appendingPathComponent("preview")
static let cssOverridesTemplateUrl = resourceUrl
.appendingPathComponent("markdown/color-overrides.css")
static let cssUrl = resourceUrl.appendingPathComponent("markdown/github-markdown.css")
static let markdownTemplateUrl = resourceUrl.appendingPathComponent("markdown/template.html")
static let baseCssUrl = previewUrl.appendingPathComponent("base.css")
static let emptyHtmlTemplateUrl = previewUrl.appendingPathComponent("empty.html")
static let errorHtmlTemplateUrl = previewUrl.appendingPathComponent("error.html")
static let saveFirstHtmlTemplateUrl = previewUrl.appendingPathComponent("save-first.html")
static let selectFirstHtmlTemplateUrl = previewUrl.appendingPathComponent("select-first.html")
}

View File

@ -137,13 +137,14 @@ struct PreviewState {
var previewPosition = Marked(Position.beginning)
var lastSearch = SearchAction.none
init(status: Status = .none,
buffer: URL? = nil,
html: URL? = nil,
server: URL? = nil,
updateDate: Date = Date(),
editorPosition: Marked<Position> = Marked(.beginning),
previewPosition: Marked<Position> = Marked(.beginning)
init(
status: Status = .none,
buffer: URL? = nil,
html: URL? = nil,
server: URL? = nil,
updateDate: Date = Date(),
editorPosition: Marked<Position> = Marked(.beginning),
previewPosition: Marked<Position> = Marked(.beginning)
) {
self.status = status
self.buffer = buffer
@ -258,7 +259,7 @@ extension MainWindow {
var preview = PreviewState.default
var htmlPreview = HtmlPreviewState.default
var previewTool = PreviewTool.State.default
var previewTool = MarkdownTool.State.default
var fileBrowserShowHidden = false
@ -449,7 +450,7 @@ struct WorkspaceToolState: Codable {
}
}
extension PreviewTool {
extension MarkdownTool {
struct State: Codable {

View File

@ -39,6 +39,18 @@ struct Theme: CustomStringConvertible {
var directoryForeground = NSColor.textColor
var cssColor = NSColor(hex: "24292e")!
var cssBackgroundColor = NSColor.white
var cssA = NSColor(hex: "0366d6")!
var cssHrBorderBackgroundColor = NSColor(hex: "dfe2e5")!
var cssHrBorderBottomColor = NSColor(hex: "eeeeee")!
var cssBlockquoteBorderLeftColor = NSColor(hex: "dfe2e5")!
var cssBlockquoteColor = NSColor(hex: "6a737d")!
var cssH2BorderBottomColor = NSColor(hex: "eaecef")!
var cssH6Color = NSColor(hex: "6a737d")!
var cssCodeColor = NSColor(hex: "24292e")!
var cssCodeBackgroundColor = NSColor(hex: "1b1f23")!
public var description: String {
return "Theme<" +
"fg: \(self.foreground.hex), bg: \(self.background.hex), " +
@ -47,17 +59,36 @@ struct Theme: CustomStringConvertible {
">"
}
init() {
init() {}
init(from nvimTheme: NvimView.Theme, additionalColorDict: [String: CellAttributes]) {
self.foreground = nvimTheme.foreground
self.background = nvimTheme.background
self.highlightForeground = nvimTheme.visualForeground
self.highlightBackground = nvimTheme.visualBackground
self.directoryForeground = nvimTheme.directoryForeground
self.updateCssColors(additionalColorDict)
}
init(_ neoVimTheme: NvimView.Theme) {
self.foreground = neoVimTheme.foreground
self.background = neoVimTheme.background
private mutating func updateCssColors(_ colors: [String: CellAttributes]) {
guard let normal = colors["Normal"],
let directory = colors["Directory"],
let question = colors["Question"],
let cursorColumn = colors["CursorColumn"] else { return }
self.highlightForeground = neoVimTheme.visualForeground
self.highlightBackground = neoVimTheme.visualBackground
self.directoryForeground = neoVimTheme.directoryForeground
self.cssColor = NSColor(rgb: normal.effectiveForeground)
self.cssBackgroundColor = NSColor(rgb: normal.effectiveBackground)
self.cssA = NSColor(rgb: directory.effectiveForeground)
self.cssHrBorderBackgroundColor = NSColor(rgb: cursorColumn.effectiveForeground)
self.cssHrBorderBottomColor = NSColor(rgb: cursorColumn.effectiveBackground)
self.cssBlockquoteBorderLeftColor = NSColor(rgb: cursorColumn.effectiveForeground)
self.cssBlockquoteColor = NSColor(rgb: question.effectiveBackground)
self.cssH2BorderBottomColor = NSColor(rgb: cursorColumn.effectiveBackground)
self.cssH6Color = NSColor(rgb: normal.effectiveForeground)
self.cssCodeColor = NSColor(rgb: cursorColumn.effectiveForeground)
self.cssCodeBackgroundColor = NSColor(rgb: cursorColumn.effectiveBackground)
}
}

View File

@ -0,0 +1,45 @@
:root {
--nvim-color: {{ nvim-color }};
--nvim-background-color: {{ nvim-background-color }};
--nvim-a: {{ nvim-a }};
--nvim-hr-background-color: {{ nvim-hr-background-color }};
--nvim-hr-border-bottom-color: {{ nvim-hr-border-bottom-color }};
--nvim-blockquote-border-left-color: {{ nvim-blockquote-border-left-color }};
--nvim-blockquote-color: {{ nvim-blockquote-color }};
--nvim-h2-border-bottom-color: {{ nvim-h2-border-bottom-color }};
--nvim-h6-color: {{ nvim-h6-color }};
--nvim-code-background-color: {{ nvim-code-background-color }};
--nvim-code-color: {{ nvim-code-color }};
}
.markdown-body {
color: var(--nvim-color);
background-color: var(--nvim-background-color);
}
.markdown-body a {
color: var(--nvim-a);
}
.markdown-body hr {
background-color: var(--nvim-hr-background-color);
border-bottom-color: var(--nvim-hr-border-bottom-color);
}
.markdown-body blockquote {
border-left-color: var(--nvim-blockquote-border-left-color);
color: var(--nvim-blockquote-foreground);
}
.markdown-body h2 {
border-bottom-color: var(--nvim-border-bottom-color);
}
.markdown-body h6 {
color: var(--nvim-h6-color);
}
.markdown-body pre {
color: var(--nvim-code-color);
background-color: var(--nvim-code-background-color);
}

View File

@ -3,6 +3,9 @@
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="github-markdown.css">
<style>
{{ css-overrides }}
</style>
<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>
<script>
// Scrolling

View File

@ -4,9 +4,12 @@
<meta charset="UTF-8">
<link rel="stylesheet" href="github-markdown.css">
<link rel="stylesheet" href="base.css">
<style>
{{ css-overrides }}
</style>
<title>Empty</title>
</head>
<body>
<body class="markdown-body">
<div id="message">
<h1>😶</h1>
<span class="info-text">no preview...</span>

View File

@ -4,9 +4,12 @@
<meta charset="UTF-8">
<link rel="stylesheet" href="github-markdown.css">
<link rel="stylesheet" href="base.css">
<style>
{{ css-overrides }}
</style>
<title>Error</title>
</head>
<body>
<body class="markdown-body">
<div id="message">
<h1>😱</h1>
<span class="info-text">There was an error...</span>

View File

@ -4,9 +4,12 @@
<meta charset="UTF-8">
<link rel="stylesheet" href="github-markdown.css">
<link rel="stylesheet" href="base.css">
<style>
{{ css-overrides }}
</style>
<title>Error</title>
</head>
<body>
<body class="markdown-body">
<div id="message">
<h1>😶</h1>
<span class="info-text">Save first for preview</span>

View File

@ -4,9 +4,12 @@
<meta charset="UTF-8">
<link rel="stylesheet" href="github-markdown.css">
<link rel="stylesheet" href="base.css">
<style>
{{ css-overrides }}
</style>
<title>Error</title>
</head>
<body>
<body class="markdown-body">
<div id="message">
<h1>😶</h1>
<span class="info-text">Select an HTML file for preview</span>

View File

@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>0.32.0</string>
<string>SNAPSHOT-347</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>344</string>
<string>347</string>
</dict>
</plist>

View File

@ -7,36 +7,22 @@
<description>Most recent changes with links to updates for VimR.</description>
<language>en</language>
<item>
<title>v0.32.0-344</title>
<title>SNAPSHOT-347</title>
<description><![CDATA[
<p>We updated the library ShortcutRecorder to the latest version. By doing so, we store the shortcuts in a different format than before. This means that after you launched this version, old versions will not be compatible with the stored shortcuts. To delete the stored shortcuts, you can use <code>defaults delete com.qvacua.VimR.menuitems</code> in Terminal.</p>
<ul>
<li>Show only font family names of monospace fonts.</li>
<li>Set <code>gui_running</code> to <code>true</code> (GH-476).</li>
<ul>
<li>Improve drawing performance.</li>
<li>Bugfix: The cursor is not drawn when a new window is opened.</li>
<li>Bugfix: Preview in the Appearance preferences is not dark mode compatible.</li>
<li>Bugfix: Shortcut buttons are not dark mode compatible.</li>
<li>Dependencies updates:<ul>
<li>Kentzo/ShortcutRecorder@3.1</li>
<li>httpswift/swifter@1.4.7</li>
<li>eonil/FSEvents@0.1.6</li>
<li>Quick/Nimble@8.0.5</li>
<li>sparkle-project/Sparkle@1.22.0</li>
</ul>
</li>
</ul>
]]></description>
<releaseNotesLink>
https://github.com/qvacua/vimr/releases/tag/v0.32.0-344
https://github.com/qvacua/vimr/releases/tag/snapshot/347
</releaseNotesLink>
<pubDate>2020-02-13T07:21:41.236766</pubDate>
<pubDate>2020-03-10T21:36:52.552729</pubDate>
<minimumSystemVersion>10.12.0</minimumSystemVersion>
<enclosure url="https://github.com/qvacua/vimr/releases/download/v0.32.0-344/VimR-v0.32.0-344.tar.bz2"
sparkle:version="344"
sparkle:shortVersionString="0.32.0"
sparkle:dsaSignature="MC0CFCE5p6Ko2mVWpubSEj6LKh6wQAH3AhUAvKcBfpeadJ2Pl1qqYChrWWkpwBY="
length="14813066"
<enclosure url="https://github.com/qvacua/vimr/releases/download/snapshot/347/VimR-SNAPSHOT-347.tar.bz2"
sparkle:version="347"
sparkle:shortVersionString="SNAPSHOT-347"
sparkle:dsaSignature="MCwCFFJBf//mmjwwPtTUwsMwxcfAsVOOAhQ2dOcIku8wb+DHCfQW97AKaqj7fA=="
length="14983113"
type="application/octet-stream"/>
</item>
</channel>

View File

@ -34,7 +34,7 @@ if [[ "${is_snapshot}" == false ]] && [[ "${update_appcast}" == false ]] ; then
exit 1
fi
if [[ "${publish}" == false ]] && [[ "${use_cache_carthage}" == true ]] ; then
if [[ "${publish}" == true ]] && [[ "${use_cache_carthage}" == true ]] ; then
echo "### ERROR Publishing, but using cache for Carthage!"
exit 1
fi
@ -44,11 +44,6 @@ if [[ "${is_snapshot}" == false ]] && [[ "${branch}" != "master" ]] ; then
exit 1
fi
if [[ "${is_snapshot}" == true ]] && [[ "${branch}" == "master" ]] ; then
echo "### ERROR Building master for snapshot!"
exit 1
fi
git lfs install
echo "### Installing some python packages"

View File

@ -64,7 +64,7 @@ if [[ ${code_sign} == true ]] ; then
pushd ${build_path}/Build/Products/Release > /dev/null
codesign --force -s "${identity}" --timestamp --options=runtime --entitlements="${entitlements_path}" \
VimR.app/Contents/Frameworks/NvimView.framework/Versions/A/NvimServer
codesign --force -s "${identity}" --deep --timestamp --options=runtime VimR.app/Contents/Frameworks/NvimView.framework/Versions/A
codesign --force -s "${identity}" --timestamp --options=runtime VimR.app/Contents/Frameworks/NvimView.framework/Versions/A
codesign --force -s "${identity}" --deep --timestamp --options=runtime VimR.app/Contents/Frameworks/Sparkle.framework/Versions/A/Resources/Autoupdate.app
codesign --force -s "${identity}" --deep --timestamp --options=runtime VimR.app/Contents/Frameworks/Sparkle.framework/Versions/A
popd > /dev/null

View File

@ -1,5 +1,7 @@
# Next
* GH-775: Use the colors of the selected color scheme for the markdown preview.
* Improve drawing performance.
* Dependencies updates:
- ggreer/the_silver_searcher@a509a81
- sparkle-project/Sparkle@1.23.0