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:
commit
fc7ce69ce4
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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"/>
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -29,7 +29,7 @@ class Document: NSDocument, NSWindowDelegate {
|
||||
|
||||
case .neoVimStopped: self.close()
|
||||
|
||||
default: break //Swift.print("Event received: \(event)")
|
||||
default: break
|
||||
|
||||
}
|
||||
})
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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] = [:]
|
||||
|
@ -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)
|
||||
|
@ -19,6 +19,7 @@ class ConditionVariable {
|
||||
|
||||
while !self.posted {
|
||||
self.condition.wait(until: Date(timeIntervalSinceNow: seconds))
|
||||
self.posted = true
|
||||
}
|
||||
|
||||
fn?()
|
||||
|
59
NvimView/NvimView/FifoCache.swift
Normal file
59
NvimView/NvimView/FifoCache.swift
Normal 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)
|
||||
}
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -379,7 +379,7 @@ extension NvimView {
|
||||
) else {
|
||||
self.bridgeLogger.error("Could not convert \(value)")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let theme = Theme(values)
|
||||
self.bridgeLogger.debug(theme)
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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}> {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -19,6 +19,7 @@ class ConditionVariable {
|
||||
|
||||
while !self.posted {
|
||||
self.condition.wait(until: Date(timeIntervalSinceNow: seconds))
|
||||
self.posted = true
|
||||
}
|
||||
|
||||
fn?()
|
||||
|
@ -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
38
VimR/VimR/CssUtils.swift
Normal 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)" }
|
||||
}
|
@ -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"
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
52
VimR/VimR/HtmlPreviewMiddleware.swift
Normal file
52
VimR/VimR/HtmlPreviewMiddleware.swift
Normal 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
|
||||
}
|
@ -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") }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
185
VimR/VimR/MarkdownPreviewMiddleware.swift
Normal file
185
VimR/VimR/MarkdownPreviewMiddleware.swift
Normal 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
|
||||
}
|
||||
}
|
222
VimR/VimR/MarkdownPreviewReducer.swift
Normal file
222
VimR/VimR/MarkdownPreviewReducer.swift
Normal 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"
|
@ -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))
|
@ -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
|
@ -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! }
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
23
VimR/VimR/Resources.swift
Normal 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")
|
||||
}
|
@ -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 {
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
45
VimR/VimR/markdown/color-overrides.css
Normal file
45
VimR/VimR/markdown/color-overrides.css
Normal 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);
|
||||
}
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user