mirror of
https://github.com/qvacua/vimr.git
synced 2024-08-16 20:20:28 +03:00
Extract Commons
This commit is contained in:
parent
2cb2fde084
commit
ca77228249
5
Commons/.gitignore
vendored
Normal file
5
Commons/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
24
Commons/Package.swift
Normal file
24
Commons/Package.swift
Normal file
@ -0,0 +1,24 @@
|
||||
// swift-tools-version:5.3
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Commons",
|
||||
platforms: [.macOS(.v10_13)],
|
||||
products: [
|
||||
.library(
|
||||
name: "Commons",
|
||||
targets: ["Commons"]),
|
||||
],
|
||||
dependencies: [],
|
||||
targets: [
|
||||
.target(
|
||||
name: "Commons",
|
||||
dependencies: []
|
||||
),
|
||||
.testTarget(
|
||||
name: "CommonsTests",
|
||||
dependencies: ["Commons"]
|
||||
),
|
||||
]
|
||||
)
|
3
Commons/README.md
Normal file
3
Commons/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Commons
|
||||
|
||||
A description of this package.
|
128
Commons/Sources/Commons/AppKitCommons.swift
Normal file
128
Commons/Sources/Commons/AppKitCommons.swift
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import AppKit
|
||||
|
||||
public extension NSColor {
|
||||
|
||||
static var random: NSColor {
|
||||
NSColor(
|
||||
calibratedRed: .random(in: 0...1),
|
||||
green: .random(in: 0...1),
|
||||
blue: .random(in: 0...1),
|
||||
alpha: 1.0
|
||||
)
|
||||
}
|
||||
|
||||
var int: Int {
|
||||
if let color = self.usingColorSpace(.sRGB) {
|
||||
let a = Int(color.alphaComponent * 255)
|
||||
let r = Int(color.redComponent * 255)
|
||||
let g = Int(color.greenComponent * 255)
|
||||
let b = Int(color.blueComponent * 255)
|
||||
return a << 24 | r << 16 | g << 8 | b
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
|
||||
let h = color.hueComponent
|
||||
let s = color.saturationComponent
|
||||
let b = color.brightnessComponent
|
||||
let a = color.alphaComponent
|
||||
|
||||
return NSColor(hue: h, saturation: s, brightness: b * factor, alpha: a)
|
||||
}
|
||||
}
|
||||
|
||||
public extension NSImage {
|
||||
|
||||
func tinting(with color: NSColor) -> NSImage {
|
||||
let result = self.copy() as! NSImage
|
||||
|
||||
result.lockFocus()
|
||||
color.set()
|
||||
CGRect(origin: .zero, size: self.size).fill(using: .sourceAtop)
|
||||
result.unlockFocus()
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
public extension NSButton {
|
||||
|
||||
var boolState: Bool {
|
||||
get { self.state == .on ? true : false }
|
||||
set { self.state = newValue ? .on : .off }
|
||||
}
|
||||
}
|
||||
|
||||
public extension NSMenuItem {
|
||||
|
||||
var boolState: Bool {
|
||||
get { self.state == .on ? true : false }
|
||||
set { self.state = newValue ? .on : .off }
|
||||
}
|
||||
}
|
||||
|
||||
public extension NSView {
|
||||
|
||||
func removeAllSubviews() { self.subviews.forEach { $0.removeFromSuperview() } }
|
||||
|
||||
func removeAllConstraints() { self.removeConstraints(self.constraints) }
|
||||
|
||||
func beFirstResponder() { self.window?.makeFirstResponder(self) }
|
||||
|
||||
/// - Returns: Rects currently being drawn
|
||||
/// - Warning: Call only in drawRect()
|
||||
func rectsBeingDrawn() -> [CGRect] {
|
||||
var rectsPtr: UnsafePointer<CGRect>? = nil
|
||||
var count: Int = 0
|
||||
self.getRectsBeingDrawn(&rectsPtr, count: &count)
|
||||
|
||||
return Array(UnsafeBufferPointer(start: rectsPtr, count: count))
|
||||
}
|
||||
}
|
||||
|
||||
public extension NSEvent.ModifierFlags {
|
||||
|
||||
// Values are from https://github.com/SFML/SFML/blob/master/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm
|
||||
// @formatter:off
|
||||
static let rightShift = NSEvent.ModifierFlags(rawValue: 0x020004)
|
||||
static let leftShift = NSEvent.ModifierFlags(rawValue: 0x020002)
|
||||
static let rightCommand = NSEvent.ModifierFlags(rawValue: 0x100010)
|
||||
static let leftCommand = NSEvent.ModifierFlags(rawValue: 0x100008)
|
||||
static let rightOption = NSEvent.ModifierFlags(rawValue: 0x080040)
|
||||
static let leftOption = NSEvent.ModifierFlags(rawValue: 0x080020)
|
||||
static let rightControl = NSEvent.ModifierFlags(rawValue: 0x042000)
|
||||
static let leftControl = NSEvent.ModifierFlags(rawValue: 0x040001)
|
||||
// @formatter:on
|
||||
}
|
@ -5,21 +5,21 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
extension CFRange {
|
||||
public extension CFRange {
|
||||
|
||||
static let zero = CFRange(location: 0, length: 0)
|
||||
}
|
||||
|
||||
extension CGSize {
|
||||
public extension CGSize {
|
||||
|
||||
func scaling(_ factor: CGFloat) -> CGSize {
|
||||
return CGSize(width: self.width * factor, height: self.height * factor)
|
||||
}
|
||||
}
|
||||
|
||||
extension CGRect {
|
||||
public extension CGRect {
|
||||
|
||||
public var hashValue: Int {
|
||||
var hashValue: Int {
|
||||
let o = Int(self.origin.x) << 10 ^ Int(self.origin.y)
|
||||
let s = Int(self.size.width) << 10 ^ Int(self.size.height)
|
||||
return o + s
|
185
Commons/Sources/Commons/FoundationCommons.swift
Normal file
185
Commons/Sources/Commons/FoundationCommons.swift
Normal file
@ -0,0 +1,185 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
public extension Array where Element: Hashable {
|
||||
|
||||
// From https://stackoverflow.com/a/46354989/9850227
|
||||
func uniqued() -> [Element] {
|
||||
var seen = Set<Element>()
|
||||
return self.filter { seen.insert($0).inserted }
|
||||
}
|
||||
}
|
||||
|
||||
public extension Array {
|
||||
|
||||
func data() -> Data {
|
||||
return self.withUnsafeBufferPointer(Data.init)
|
||||
}
|
||||
}
|
||||
|
||||
public extension RandomAccessCollection where Index == Int {
|
||||
|
||||
func parallelMap<T>(
|
||||
chunkSize: Int = 1,
|
||||
_ transform: @escaping (Element) -> T
|
||||
) -> [T] {
|
||||
let count = self.count
|
||||
guard count > chunkSize else { return self.map(transform) }
|
||||
|
||||
var result = Array<T?>(repeating: nil, count: count)
|
||||
|
||||
// If we don't use Array.withUnsafeMutableBufferPointer,
|
||||
// then we get crashes.
|
||||
result.withUnsafeMutableBufferPointer { pointer in
|
||||
if chunkSize == 1 {
|
||||
DispatchQueue.concurrentPerform(iterations: count) { i in
|
||||
pointer[i] = transform(self[i])
|
||||
}
|
||||
} else {
|
||||
let chunkCount = Int(ceil(Double(self.count) / Double(chunkSize)))
|
||||
DispatchQueue.concurrentPerform(iterations: chunkCount) { chunkIndex in
|
||||
let start = Swift.min(chunkIndex * chunkSize, count)
|
||||
let end = Swift.min(start + chunkSize, count)
|
||||
|
||||
(start..<end).forEach { i in pointer[i] = transform(self[i]) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.map { $0! }
|
||||
}
|
||||
|
||||
func groupedRanges<T: Equatable>(
|
||||
with marker: (Index, Element) -> T
|
||||
) -> [CountableClosedRange<Index>] {
|
||||
if self.isEmpty {
|
||||
return []
|
||||
}
|
||||
|
||||
if self.count == 1 {
|
||||
return [self.startIndex...self.startIndex]
|
||||
}
|
||||
|
||||
var result = [CountableClosedRange<Index>]()
|
||||
result.reserveCapacity(self.count / 2)
|
||||
|
||||
let inclusiveEndIndex = self.endIndex - 1
|
||||
var lastStartIndex = self.startIndex
|
||||
var lastEndIndex = self.startIndex
|
||||
var lastMarker = marker(0, self.first!) // self is not empty!
|
||||
for i in self.startIndex..<self.endIndex {
|
||||
defer { lastEndIndex = i }
|
||||
|
||||
let currentMarker = marker(i, self[i])
|
||||
|
||||
if lastMarker == currentMarker {
|
||||
if i == inclusiveEndIndex {
|
||||
result.append(lastStartIndex...i)
|
||||
}
|
||||
} else {
|
||||
result.append(lastStartIndex...lastEndIndex)
|
||||
lastMarker = currentMarker
|
||||
lastStartIndex = i
|
||||
|
||||
if i == inclusiveEndIndex {
|
||||
result.append(i...i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
public extension NSRange {
|
||||
|
||||
static let notFound = NSRange(location: NSNotFound, length: 0)
|
||||
|
||||
var inclusiveEndIndex: Int { self.location + self.length - 1 }
|
||||
}
|
||||
|
||||
public extension URL {
|
||||
|
||||
func isDirectParent(of url: URL) -> Bool {
|
||||
guard self.isFileURL && url.isFileURL else { return false }
|
||||
|
||||
let myPathComps = self.pathComponents
|
||||
let targetPathComps = url.pathComponents
|
||||
|
||||
guard targetPathComps.count == myPathComps.count + 1 else { return false }
|
||||
|
||||
return Array(targetPathComps[0..<myPathComps.count]) == myPathComps
|
||||
}
|
||||
|
||||
func isParent(of url: URL) -> Bool {
|
||||
guard self.isFileURL && url.isFileURL else { return false }
|
||||
|
||||
let myPathComps = self.pathComponents
|
||||
let targetPathComps = url.pathComponents
|
||||
|
||||
guard targetPathComps.count > myPathComps.count else { return false }
|
||||
|
||||
return Array(targetPathComps[0..<myPathComps.count]) == myPathComps
|
||||
}
|
||||
|
||||
func isContained(in parentUrl: URL) -> Bool {
|
||||
if parentUrl == self { return false }
|
||||
|
||||
let pathComps = self.pathComponents
|
||||
let parentPathComps = parentUrl.pathComponents
|
||||
|
||||
guard pathComps.count > parentPathComps.count else { return false }
|
||||
|
||||
guard Array(pathComps[0..<parentPathComps.endIndex]) == parentPathComps else { return false }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
var parent: URL {
|
||||
if self.path == "/" { return self }
|
||||
|
||||
return self.deletingLastPathComponent()
|
||||
}
|
||||
|
||||
var isDir: Bool { self.resourceValue(URLResourceKey.isDirectoryKey.rawValue) }
|
||||
|
||||
var isHidden: Bool { self.resourceValue(URLResourceKey.isHiddenKey.rawValue) }
|
||||
|
||||
var isPackage: Bool { self.resourceValue(URLResourceKey.isPackageKey.rawValue) }
|
||||
|
||||
/// Wrapper function for NSURL.getResourceValue for Bool values.
|
||||
/// Returns also `false` when
|
||||
/// - there is no value for the given `key` or
|
||||
/// - the value cannot be converted to `NSNumber`.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - key: The `key`-parameter of `NSURL.getResourceValue`.
|
||||
private func resourceValue(_ key: String) -> Bool {
|
||||
var rsrc: AnyObject?
|
||||
|
||||
do {
|
||||
try (self as NSURL).getResourceValue(&rsrc, forKey: URLResourceKey(rawValue: key))
|
||||
} catch let error as NSError {
|
||||
// FIXME error handling
|
||||
log.error("ERROR while getting \(key): \(error)")
|
||||
return false
|
||||
}
|
||||
|
||||
if let result = rsrc as? NSNumber { return result.boolValue }
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public extension ValueTransformer {
|
||||
|
||||
static var keyedUnarchiveFromDataTransformer
|
||||
= ValueTransformer(forName: .keyedUnarchiveFromDataTransformerName)!
|
||||
}
|
||||
|
||||
private let log = OSLog(subsystem: "com.qvacua.vimr.commons", category: "general")
|
@ -6,7 +6,7 @@
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
extension OSLog {
|
||||
public extension OSLog {
|
||||
|
||||
func trace<T>(
|
||||
file: String = #file,
|
@ -5,19 +5,19 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
func identity<T>(_ input: T) -> T { input }
|
||||
public func identity<T>(_ input: T) -> T { input }
|
||||
|
||||
extension BinaryFloatingPoint {
|
||||
public extension BinaryFloatingPoint {
|
||||
|
||||
var cgf: CGFloat { CGFloat(self) }
|
||||
}
|
||||
|
||||
extension FixedWidthInteger {
|
||||
public extension FixedWidthInteger {
|
||||
|
||||
var cgf: CGFloat { CGFloat(self) }
|
||||
}
|
||||
|
||||
extension String {
|
||||
public extension String {
|
||||
|
||||
func without(prefix: String) -> String {
|
||||
guard self.hasPrefix(prefix) else { return self }
|
||||
@ -27,7 +27,7 @@ extension String {
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element: Equatable {
|
||||
public extension Array where Element: Equatable {
|
||||
|
||||
func removingDuplicatesPreservingFromBeginning() -> [Element] {
|
||||
var result = [Element]()
|
||||
@ -57,7 +57,7 @@ extension Array where Element: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element: Hashable {
|
||||
public extension Array where Element: Hashable {
|
||||
|
||||
func toDict<V>(by mapper: @escaping (Element) -> V) -> Dictionary<Element, V> {
|
||||
var result = Dictionary<Element, V>(minimumCapacity: self.count)
|
||||
@ -82,7 +82,7 @@ func tuplesToDict<K: Hashable, V, S: Sequence>(_ sequence: S)
|
||||
return result
|
||||
}
|
||||
|
||||
extension Dictionary {
|
||||
public extension Dictionary {
|
||||
|
||||
func mapToDict<K, V>(_ transform: ((key: Key, value: Value)) throws -> (K, V)) rethrows
|
||||
-> Dictionary<K, V> {
|
||||
@ -97,7 +97,7 @@ extension Dictionary {
|
||||
}
|
||||
}
|
||||
|
||||
extension Sequence {
|
||||
public extension Sequence {
|
||||
|
||||
@discardableResult
|
||||
func log() -> Self {
|
15
Commons/Tests/CommonsTests/CommonsTests.swift
Normal file
15
Commons/Tests/CommonsTests/CommonsTests.swift
Normal file
@ -0,0 +1,15 @@
|
||||
import XCTest
|
||||
@testable import Commons
|
||||
|
||||
final class CommonsTests: XCTestCase {
|
||||
func testExample() {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct
|
||||
// results.
|
||||
XCTAssertEqual(Commons().text, "Hello, World!")
|
||||
}
|
||||
|
||||
static var allTests = [
|
||||
("testExample", testExample),
|
||||
]
|
||||
}
|
9
Commons/Tests/CommonsTests/XCTestManifests.swift
Normal file
9
Commons/Tests/CommonsTests/XCTestManifests.swift
Normal file
@ -0,0 +1,9 @@
|
||||
import XCTest
|
||||
|
||||
#if !canImport(ObjectiveC)
|
||||
public func allTests() -> [XCTestCaseEntry] {
|
||||
return [
|
||||
testCase(CommonsTests.allTests),
|
||||
]
|
||||
}
|
||||
#endif
|
7
Commons/Tests/LinuxMain.swift
Normal file
7
Commons/Tests/LinuxMain.swift
Normal file
@ -0,0 +1,7 @@
|
||||
import XCTest
|
||||
|
||||
import CommonsTests
|
||||
|
||||
var tests = [XCTestCaseEntry]()
|
||||
tests += CommonsTests.allTests()
|
||||
XCTMain(tests)
|
@ -13,11 +13,12 @@ let package = Package(
|
||||
.package(url: "https://github.com/ReactiveX/RxSwift", .upToNextMinor(from: "5.1.1")),
|
||||
.package(name: "NvimServerTypes", url: "https://github.com/qvacua/neovim", .exact("0.1.0-types")),
|
||||
.package(name: "RxPack", path: "../RxPack"),
|
||||
.package(name: "Commons", path: "../Commons"),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "NvimView",
|
||||
dependencies: ["RxSwift", "NvimServerTypes", "RxPack", "MessagePack"],
|
||||
dependencies: ["RxSwift", "NvimServerTypes", "RxPack", "MessagePack", "Commons"],
|
||||
// com.qvacua.NvimView.vim is copied by the download NvimServer script.
|
||||
exclude: ["com.qvacua.NvimView.vim"],
|
||||
resources: [
|
||||
|
@ -6,6 +6,7 @@
|
||||
import Cocoa
|
||||
import MessagePack
|
||||
import NvimServerTypes
|
||||
import Commons
|
||||
|
||||
public struct CellAttributes: CustomStringConvertible, Equatable {
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension NSRange {
|
||||
|
||||
static let notFound = NSRange(location: NSNotFound, length: 0)
|
||||
|
||||
var inclusiveEndIndex: Int { self.location + self.length - 1 }
|
||||
}
|
||||
|
||||
extension NSColor {
|
||||
|
||||
var int: Int {
|
||||
if let color = self.usingColorSpace(.sRGB) {
|
||||
let a = Int(color.alphaComponent * 255)
|
||||
let r = Int(color.redComponent * 255)
|
||||
let g = Int(color.greenComponent * 255)
|
||||
let b = Int(color.blueComponent * 255)
|
||||
return a << 24 | r << 16 | g << 8 | b
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
var hex: String { String(format: "%X", self.int) }
|
||||
}
|
||||
|
||||
extension NSView {
|
||||
|
||||
/// - Returns: Rects currently being drawn
|
||||
/// - Warning: Call only in drawRect()
|
||||
func rectsBeingDrawn() -> [CGRect] {
|
||||
var rectsPtr: UnsafePointer<CGRect>? = nil
|
||||
var count: Int = 0
|
||||
self.getRectsBeingDrawn(&rectsPtr, count: &count)
|
||||
|
||||
return Array(UnsafeBufferPointer(start: rectsPtr, count: count))
|
||||
}
|
||||
}
|
||||
|
||||
extension NSEvent.ModifierFlags {
|
||||
|
||||
// Values are from https://github.com/SFML/SFML/blob/master/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm
|
||||
// @formatter:off
|
||||
static let rightShift = NSEvent.ModifierFlags(rawValue: 0x020004)
|
||||
static let leftShift = NSEvent.ModifierFlags(rawValue: 0x020002)
|
||||
static let rightCommand = NSEvent.ModifierFlags(rawValue: 0x100010)
|
||||
static let leftCommand = NSEvent.ModifierFlags(rawValue: 0x100008)
|
||||
static let rightOption = NSEvent.ModifierFlags(rawValue: 0x080040)
|
||||
static let leftOption = NSEvent.ModifierFlags(rawValue: 0x080020)
|
||||
static let rightControl = NSEvent.ModifierFlags(rawValue: 0x042000)
|
||||
static let leftControl = NSEvent.ModifierFlags(rawValue: 0x040001)
|
||||
// @formatter:on
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
extension OSLog {
|
||||
|
||||
func trace<T>(
|
||||
file: String = #file,
|
||||
function: String = #function,
|
||||
line: Int = #line,
|
||||
_ msg: T
|
||||
) {
|
||||
#if TRACE
|
||||
self.log(
|
||||
type: .debug,
|
||||
msg: "%{public}@",
|
||||
"[\((file as NSString).lastPathComponent) - \(function):\(line)] [TRACE]"
|
||||
)
|
||||
#endif
|
||||
}
|
||||
|
||||
func debug(
|
||||
file: String = #file,
|
||||
function: String = #function,
|
||||
line: Int = #line
|
||||
) {
|
||||
#if DEBUG
|
||||
self.log(
|
||||
type: .debug,
|
||||
msg: "%{public}@",
|
||||
"[\((file as NSString).lastPathComponent) - \(function):\(line)]"
|
||||
)
|
||||
#endif
|
||||
}
|
||||
|
||||
func debug<T>(
|
||||
file: String = #file,
|
||||
function: String = #function,
|
||||
line: Int = #line,
|
||||
_ msg: T
|
||||
) {
|
||||
#if DEBUG
|
||||
self.log(
|
||||
type: .debug,
|
||||
msg: "%{public}@",
|
||||
"[\((file as NSString).lastPathComponent) - \(function):\(line)] \(msg)"
|
||||
)
|
||||
#endif
|
||||
}
|
||||
|
||||
func info<T>(
|
||||
file: String = #file,
|
||||
function: String = #function,
|
||||
line: Int = #line,
|
||||
_ msg: T
|
||||
) {
|
||||
self.log(
|
||||
type: .info,
|
||||
msg: "%{public}@",
|
||||
"[\((file as NSString).lastPathComponent) - \(function):\(line)] \(msg)"
|
||||
)
|
||||
}
|
||||
|
||||
func `default`<T>(
|
||||
file: String = #file,
|
||||
function: String = #function,
|
||||
line: Int = #line,
|
||||
_ msg: T
|
||||
) {
|
||||
self.log(
|
||||
type: .default,
|
||||
msg: "%{public}@",
|
||||
"[\((file as NSString).lastPathComponent) - \(function):\(line)] \(msg)"
|
||||
)
|
||||
}
|
||||
|
||||
func error<T>(
|
||||
file: String = #file,
|
||||
function: String = #function,
|
||||
line: Int = #line,
|
||||
_ msg: T
|
||||
) {
|
||||
self.log(
|
||||
type: .error,
|
||||
msg: "%{public}@",
|
||||
"[\((file as NSString).lastPathComponent) - \(function):\(line)] \(msg)"
|
||||
)
|
||||
}
|
||||
|
||||
func fault<T>(
|
||||
file: String = #file,
|
||||
function: String = #function,
|
||||
line: Int = #line,
|
||||
_ msg: T
|
||||
) {
|
||||
self.log(
|
||||
type: .fault,
|
||||
msg: "%{public}@",
|
||||
"[\((file as NSString).lastPathComponent) - \(function):\(line)] \(msg)"
|
||||
)
|
||||
}
|
||||
|
||||
private func log(
|
||||
type: OSLogType,
|
||||
msg: StaticString,
|
||||
_ object: CVarArg
|
||||
) {
|
||||
os_log(msg, log: self, type: type, object)
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
extension BinaryFloatingPoint {
|
||||
|
||||
var cgf: CGFloat {
|
||||
return CGFloat(self)
|
||||
}
|
||||
}
|
||||
|
||||
extension FixedWidthInteger {
|
||||
|
||||
var cgf: CGFloat {
|
||||
return CGFloat(self)
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element: Hashable {
|
||||
|
||||
// From https://stackoverflow.com/a/46354989/9850227
|
||||
func uniqued() -> [Element] {
|
||||
var seen = Set<Element>()
|
||||
return self.filter { seen.insert($0).inserted }
|
||||
}
|
||||
}
|
||||
|
||||
extension Array {
|
||||
|
||||
func data() -> Data {
|
||||
return self.withUnsafeBufferPointer(Data.init)
|
||||
}
|
||||
}
|
||||
|
||||
extension RandomAccessCollection where Index == Int {
|
||||
|
||||
func parallelMap<T>(
|
||||
chunkSize: Int = 1,
|
||||
_ transform: @escaping (Element) -> T
|
||||
) -> [T] {
|
||||
let count = self.count
|
||||
guard count > chunkSize else { return self.map(transform) }
|
||||
|
||||
var result = Array<T?>(repeating: nil, count: count)
|
||||
|
||||
// If we don't use Array.withUnsafeMutableBufferPointer,
|
||||
// then we get crashes.
|
||||
result.withUnsafeMutableBufferPointer { pointer in
|
||||
if chunkSize == 1 {
|
||||
DispatchQueue.concurrentPerform(iterations: count) { i in
|
||||
pointer[i] = transform(self[i])
|
||||
}
|
||||
} else {
|
||||
let chunkCount = Int(ceil(Double(self.count) / Double(chunkSize)))
|
||||
DispatchQueue.concurrentPerform(iterations: chunkCount) { chunkIndex in
|
||||
let start = Swift.min(chunkIndex * chunkSize, count)
|
||||
let end = Swift.min(start + chunkSize, count)
|
||||
|
||||
(start..<end).forEach { i in pointer[i] = transform(self[i]) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.map { $0! }
|
||||
}
|
||||
|
||||
func groupedRanges<T: Equatable>(
|
||||
with marker: (Index, Element) -> T
|
||||
) -> [CountableClosedRange<Index>] {
|
||||
if self.isEmpty {
|
||||
return []
|
||||
}
|
||||
|
||||
if self.count == 1 {
|
||||
return [self.startIndex...self.startIndex]
|
||||
}
|
||||
|
||||
var result = [CountableClosedRange<Index>]()
|
||||
result.reserveCapacity(self.count / 2)
|
||||
|
||||
let inclusiveEndIndex = self.endIndex - 1
|
||||
var lastStartIndex = self.startIndex
|
||||
var lastEndIndex = self.startIndex
|
||||
var lastMarker = marker(0, self.first!) // self is not empty!
|
||||
for i in self.startIndex..<self.endIndex {
|
||||
defer { lastEndIndex = i }
|
||||
|
||||
let currentMarker = marker(i, self[i])
|
||||
|
||||
if lastMarker == currentMarker {
|
||||
if i == inclusiveEndIndex {
|
||||
result.append(lastStartIndex...i)
|
||||
}
|
||||
} else {
|
||||
result.append(lastStartIndex...lastEndIndex)
|
||||
lastMarker = currentMarker
|
||||
lastStartIndex = i
|
||||
|
||||
if i == inclusiveEndIndex {
|
||||
result.append(i...i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
3
VimR.xcworkspace/contents.xcworkspacedata
generated
3
VimR.xcworkspace/contents.xcworkspacedata
generated
@ -1,6 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Commons">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:RxPack">
|
||||
</FileRef>
|
||||
|
@ -51,7 +51,7 @@
|
||||
"repositoryURL": "https://github.com/qvacua/neovim",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "246da2521cdf3720b11a5045720d2ae1497a9268",
|
||||
"revision": "13be312e380e7f93878486c8851a605a4e7af0eb",
|
||||
"version": "0.1.0-types"
|
||||
}
|
||||
},
|
||||
|
@ -7,7 +7,6 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1929B0153C780675EE33F9EC /* AttributedStringMarkdownStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD6439FB8568CD045A41 /* AttributedStringMarkdownStyler.swift */; };
|
||||
1929B04CE8ECBD75CBBB0991 /* StringCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5D45C9792BBE76B8AFF /* StringCommonsTest.swift */; };
|
||||
1929B05B9D664052EC2D23EF /* FileOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BCE3E156C06EDF1F2806 /* FileOutlineView.swift */; };
|
||||
1929B0C7150100A84FBDB8BF /* ShortcutItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF230875DED6CD7AB3EB /* ShortcutItem.swift */; };
|
||||
@ -31,7 +30,6 @@
|
||||
1929B4B00D7BB191A9A6532D /* HtmlPreviewToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE5AEA3D0980860EED50 /* HtmlPreviewToolReducer.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 */; };
|
||||
1929B4FEE6EB56EF3F56B805 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B34FC23D805A8B29E8F7 /* Context.swift */; };
|
||||
1929B50D933A369A86A165DE /* AdvencedPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBE0A534F2F6009D31BE /* AdvencedPref.swift */; };
|
||||
@ -96,8 +94,6 @@
|
||||
4B6423981D8EFDE000FC78C8 /* WorkspaceBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6423971D8EFDE000FC78C8 /* WorkspaceBar.swift */; };
|
||||
4B64239A1D8EFE3000FC78C8 /* WorkspaceTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6423991D8EFE3000FC78C8 /* WorkspaceTool.swift */; };
|
||||
4B6A70941D60E04200E12030 /* AppKitCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70931D60E04200E12030 /* AppKitCommons.swift */; };
|
||||
4B6A70961D6100E300E12030 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70951D6100E300E12030 /* SwiftCommons.swift */; };
|
||||
4B6DFB3A22366D140066BB43 /* OSLogCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE867BD8F0ED0246CC94 /* OSLogCommons.swift */; };
|
||||
4B9433DC20B95EC6005807BA /* MacVim-bsh.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4B9433A120B95EC1005807BA /* MacVim-bsh.icns */; };
|
||||
4B9433DD20B95EC6005807BA /* MacVim-generic.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4B9433A220B95EC1005807BA /* MacVim-generic.icns */; };
|
||||
4B9433DE20B95EC6005807BA /* MacVim-dylan.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4B9433A320B95EC1005807BA /* MacVim-dylan.icns */; };
|
||||
@ -160,7 +156,6 @@
|
||||
4B96FB3C1EBBC56F00E4E164 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
|
||||
4B96FB3F1EBBC56F00E4E164 /* PrefUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B8241CDE58F7AAF89AE4 /* PrefUtils.swift */; };
|
||||
4B96FB401EBBC56F00E4E164 /* FoundationCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */; };
|
||||
4B96FB421EBBC56F00E4E164 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70951D6100E300E12030 /* SwiftCommons.swift */; };
|
||||
4B97E2CC1D33F53D00FC0660 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B97E2CE1D33F53D00FC0660 /* MainWindow.xib */; };
|
||||
4B9BC41E24EB2E22000209B5 /* MessagePack in Frameworks */ = {isa = PBXBuildFile; productRef = 4B9BC41D24EB2E22000209B5 /* MessagePack */; };
|
||||
4B9BC42124EB2E45000209B5 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 4B9BC42024EB2E45000209B5 /* RxCocoa */; };
|
||||
@ -178,6 +173,7 @@
|
||||
4BD5657824E8443300D52809 /* DictionaryCoding in Frameworks */ = {isa = PBXBuildFile; productRef = 4BD5657724E8443300D52809 /* DictionaryCoding */; };
|
||||
4BD5657B24E8448300D52809 /* EonilFSEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 4BD5657A24E8448300D52809 /* EonilFSEvents */; };
|
||||
4BD67C7824EC488200147C51 /* RxPack in Frameworks */ = {isa = PBXBuildFile; productRef = 4BD67C7724EC488200147C51 /* RxPack */; };
|
||||
4BD67C7B24EC765900147C51 /* Commons in Frameworks */ = {isa = PBXBuildFile; productRef = 4BD67C7A24EC765900147C51 /* Commons */; };
|
||||
4BDF500C1D760A3500D8FBC3 /* FileUtilsTest in Resources */ = {isa = PBXBuildFile; fileRef = 4BDF500B1D760A3500D8FBC3 /* FileUtilsTest */; };
|
||||
4BDF50171D77540900D8FBC3 /* OpenQuicklyWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BDF50191D77540900D8FBC3 /* OpenQuicklyWindow.xib */; };
|
||||
4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBA5081CFF374B00673FDF /* AppDelegate.swift */; };
|
||||
@ -311,7 +307,6 @@
|
||||
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>"; };
|
||||
1929BD4149D5A25C82064DD8 /* UiRoot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiRoot.swift; sourceTree = "<group>"; };
|
||||
1929BD6439FB8568CD045A41 /* AttributedStringMarkdownStyler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributedStringMarkdownStyler.swift; sourceTree = "<group>"; };
|
||||
1929BD83A13BF133741766CC /* MainWindowReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowReducer.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
@ -319,7 +314,6 @@
|
||||
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 /* MarkdownToolReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownToolReducer.swift; sourceTree = "<group>"; };
|
||||
@ -337,7 +331,6 @@
|
||||
4B6423971D8EFDE000FC78C8 /* WorkspaceBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WorkspaceBar.swift; path = Workspace/WorkspaceBar.swift; sourceTree = "<group>"; };
|
||||
4B6423991D8EFE3000FC78C8 /* WorkspaceTool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WorkspaceTool.swift; path = Workspace/WorkspaceTool.swift; sourceTree = "<group>"; };
|
||||
4B6A70931D60E04200E12030 /* AppKitCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppKitCommons.swift; sourceTree = "<group>"; };
|
||||
4B6A70951D6100E300E12030 /* SwiftCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftCommons.swift; sourceTree = "<group>"; };
|
||||
4B8C64CD23F02259008733D8 /* Dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Dev.xcconfig; sourceTree = "<group>"; };
|
||||
4B8C64CE23F022C2008733D8 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
4B9433A120B95EC1005807BA /* MacVim-bsh.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = "MacVim-bsh.icns"; path = "macvim-file-icons/MacVim-bsh.icns"; sourceTree = "<group>"; };
|
||||
@ -435,6 +428,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4BD67C7B24EC765900147C51 /* Commons in Frameworks */,
|
||||
4B9BC42124EB2E45000209B5 /* RxCocoa in Frameworks */,
|
||||
4BD67C7824EC488200147C51 /* RxPack in Frameworks */,
|
||||
4B9BC42724EB2E51000209B5 /* NvimView in Frameworks */,
|
||||
@ -795,9 +789,6 @@
|
||||
4BF70ED123D1B4AF009E51E9 /* FoundationCommons.m */,
|
||||
4B6A70931D60E04200E12030 /* AppKitCommons.swift */,
|
||||
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */,
|
||||
4B6A70951D6100E300E12030 /* SwiftCommons.swift */,
|
||||
1929BE867BD8F0ED0246CC94 /* OSLogCommons.swift */,
|
||||
1929BD6439FB8568CD045A41 /* AttributedStringMarkdownStyler.swift */,
|
||||
);
|
||||
name = Commons;
|
||||
sourceTree = "<group>";
|
||||
@ -920,6 +911,7 @@
|
||||
4B9BC42624EB2E51000209B5 /* NvimView */,
|
||||
4B9BC42924EB2E6D000209B5 /* ShortcutRecorder */,
|
||||
4BD67C7724EC488200147C51 /* RxPack */,
|
||||
4BD67C7A24EC765900147C51 /* Commons */,
|
||||
);
|
||||
productName = VimR;
|
||||
productReference = 4BEBA5051CFF374B00673FDF /* VimR.app */;
|
||||
@ -1112,7 +1104,6 @@
|
||||
4B6A70941D60E04200E12030 /* AppKitCommons.swift in Sources */,
|
||||
4B3965361DEB21300082D3C1 /* InnterToolBar.swift in Sources */,
|
||||
4B6423981D8EFDE000FC78C8 /* WorkspaceBar.swift in Sources */,
|
||||
4B6A70961D6100E300E12030 /* SwiftCommons.swift in Sources */,
|
||||
4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */,
|
||||
4B64239A1D8EFE3000FC78C8 /* WorkspaceTool.swift in Sources */,
|
||||
1929B67DA3EB21A631EF1DBB /* FileUtils.swift in Sources */,
|
||||
@ -1179,7 +1170,6 @@
|
||||
1929B250DB3FB395A700FE8C /* RpcEvents.swift in Sources */,
|
||||
1929BF3253594E5B1908C6CE /* RpcAppearanceEpic.swift in Sources */,
|
||||
4BF70EED23D1B618009E51E9 /* ConditionVariable.swift in Sources */,
|
||||
1929B4E8B916008399CD5D3A /* OSLogCommons.swift in Sources */,
|
||||
1929B5A0EDD1119CFF7BB84C /* Defs.swift in Sources */,
|
||||
1929B376DB09AB5FDBF42BA1 /* MainWindow+Types.swift in Sources */,
|
||||
1929B443B7AB2176A7818CA1 /* fuzzy_match.cc in Sources */,
|
||||
@ -1188,7 +1178,6 @@
|
||||
1929B223C6E97C090474B2C2 /* Resources.swift in Sources */,
|
||||
1929BC64D3C195A92BE3FD64 /* HtmlPreviewMiddleware.swift in Sources */,
|
||||
1929B29FF537A339CF4075BD /* CssUtils.swift in Sources */,
|
||||
1929B0153C780675EE33F9EC /* AttributedStringMarkdownStyler.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1196,11 +1185,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4B6DFB3A22366D140066BB43 /* OSLogCommons.swift in Sources */,
|
||||
4B96FB3C1EBBC56F00E4E164 /* FileUtils.swift in Sources */,
|
||||
4B96FB3F1EBBC56F00E4E164 /* PrefUtils.swift in Sources */,
|
||||
4B96FB401EBBC56F00E4E164 /* FoundationCommons.swift in Sources */,
|
||||
4B96FB421EBBC56F00E4E164 /* SwiftCommons.swift in Sources */,
|
||||
1929B66F795867B8C07FAAD4 /* DictionaryCommonsTest.swift in Sources */,
|
||||
1929B98F94536E3912AD9F3B /* ArrayCommonsTest.swift in Sources */,
|
||||
1929BDFDBDA7180D02ACB37E /* RxSwiftCommonsTest.swift in Sources */,
|
||||
@ -1652,6 +1639,10 @@
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = RxPack;
|
||||
};
|
||||
4BD67C7A24EC765900147C51 /* Commons */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = Commons;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 4BEBA4FD1CFF374B00673FDF /* Project object */;
|
||||
|
@ -10,6 +10,7 @@ import Sparkle
|
||||
import CocoaFontAwesome
|
||||
import DictionaryCoding
|
||||
import os
|
||||
import Commons
|
||||
|
||||
let debugMenuItemIdentifier = NSUserInterfaceItemIdentifier("debug-menu-item")
|
||||
|
||||
|
@ -6,93 +6,12 @@
|
||||
import Cocoa
|
||||
import Down
|
||||
|
||||
extension NSColor {
|
||||
|
||||
static var random: NSColor {
|
||||
NSColor(
|
||||
calibratedRed: .random(in: 0...1),
|
||||
green: .random(in: 0...1),
|
||||
blue: .random(in: 0...1),
|
||||
alpha: 1.0
|
||||
)
|
||||
}
|
||||
|
||||
var int: Int {
|
||||
if let color = self.usingColorSpace(.sRGB) {
|
||||
let a = Int(color.alphaComponent * 255)
|
||||
let r = Int(color.redComponent * 255)
|
||||
let g = Int(color.greenComponent * 255)
|
||||
let b = Int(color.blueComponent * 255)
|
||||
return a << 24 | r << 16 | g << 8 | b
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
|
||||
let h = color.hueComponent
|
||||
let s = color.saturationComponent
|
||||
let b = color.brightnessComponent
|
||||
let a = color.alphaComponent
|
||||
|
||||
return NSColor(hue: h, saturation: s, brightness: b * factor, alpha: a)
|
||||
}
|
||||
extension NSView {
|
||||
|
||||
@objc var isFirstResponder: Bool { self.window?.firstResponder == self }
|
||||
}
|
||||
|
||||
extension NSImage {
|
||||
|
||||
func tinting(with color: NSColor) -> NSImage {
|
||||
let result = self.copy() as! NSImage
|
||||
|
||||
result.lockFocus()
|
||||
color.set()
|
||||
CGRect(origin: .zero, size: self.size).fill(using: .sourceAtop)
|
||||
result.unlockFocus()
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
extension NSButton {
|
||||
|
||||
var boolState: Bool {
|
||||
get { self.state == .on ? true : false }
|
||||
set { self.state = newValue ? .on : .off }
|
||||
}
|
||||
}
|
||||
|
||||
extension NSMenuItem {
|
||||
|
||||
var boolState: Bool {
|
||||
get { self.state == .on ? true : false }
|
||||
set { self.state = newValue ? .on : .off }
|
||||
}
|
||||
}
|
||||
|
||||
extension NSAttributedString {
|
||||
|
||||
@ -128,17 +47,6 @@ extension NSAttributedString {
|
||||
}
|
||||
}
|
||||
|
||||
extension NSView {
|
||||
|
||||
func removeAllSubviews() { self.subviews.forEach { $0.removeFromSuperview() } }
|
||||
|
||||
func removeAllConstraints() { self.removeConstraints(self.constraints) }
|
||||
|
||||
@objc var isFirstResponder: Bool { self.window?.firstResponder == self }
|
||||
|
||||
func beFirstResponder() { self.window?.makeFirstResponder(self) }
|
||||
}
|
||||
|
||||
extension NSTableView {
|
||||
|
||||
static func standardTableView() -> NSTableView {
|
||||
@ -238,6 +146,54 @@ extension NSScrollView {
|
||||
}
|
||||
}
|
||||
|
||||
private class AttributedStringMarkdownStyler {
|
||||
|
||||
static func new() -> Styler {
|
||||
let fonts = StaticFontCollection(
|
||||
body: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize),
|
||||
code: NSFont.userFixedPitchFont(ofSize: NSFont.smallSystemFontSize)!
|
||||
)
|
||||
|
||||
let style = DownStylerConfiguration(fonts: fonts, paragraphStyles: ParagraphStyles())
|
||||
return DownStyler(configuration: style)
|
||||
}
|
||||
}
|
||||
|
||||
private struct ParagraphStyles: ParagraphStyleCollection {
|
||||
|
||||
let heading1: NSParagraphStyle
|
||||
let heading2: NSParagraphStyle
|
||||
let heading3: NSParagraphStyle
|
||||
let heading4: NSParagraphStyle
|
||||
let heading5: NSParagraphStyle
|
||||
let heading6: NSParagraphStyle
|
||||
let body: NSParagraphStyle
|
||||
let code: NSParagraphStyle
|
||||
|
||||
public init() {
|
||||
let headingStyle = NSParagraphStyle()
|
||||
|
||||
let bodyStyle = NSMutableParagraphStyle()
|
||||
bodyStyle.paragraphSpacingBefore = 2
|
||||
bodyStyle.paragraphSpacing = 2
|
||||
bodyStyle.lineSpacing = 2
|
||||
|
||||
let codeStyle = NSMutableParagraphStyle()
|
||||
codeStyle.paragraphSpacingBefore = 2
|
||||
codeStyle.paragraphSpacing = 2
|
||||
|
||||
self.heading1 = headingStyle
|
||||
self.heading2 = headingStyle
|
||||
self.heading3 = headingStyle
|
||||
self.heading4 = headingStyle
|
||||
self.heading5 = headingStyle
|
||||
self.heading6 = headingStyle
|
||||
self.body = bodyStyle
|
||||
self.code = codeStyle
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private let fontCollection = StaticFontCollection(
|
||||
body: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize),
|
||||
code: NSFont.userFixedPitchFont(ofSize: NSFont.smallSystemFontSize)!
|
||||
|
@ -1,54 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import Down
|
||||
|
||||
class AttributedStringMarkdownStyler {
|
||||
|
||||
static func new() -> Styler {
|
||||
let fonts = StaticFontCollection(
|
||||
body: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize),
|
||||
code: NSFont.userFixedPitchFont(ofSize: NSFont.smallSystemFontSize)!
|
||||
)
|
||||
|
||||
let style = DownStylerConfiguration(fonts: fonts, paragraphStyles: ParagraphStyles())
|
||||
return DownStyler(configuration: style)
|
||||
}
|
||||
}
|
||||
|
||||
private struct ParagraphStyles: ParagraphStyleCollection {
|
||||
|
||||
let heading1: NSParagraphStyle
|
||||
let heading2: NSParagraphStyle
|
||||
let heading3: NSParagraphStyle
|
||||
let heading4: NSParagraphStyle
|
||||
let heading5: NSParagraphStyle
|
||||
let heading6: NSParagraphStyle
|
||||
let body: NSParagraphStyle
|
||||
let code: NSParagraphStyle
|
||||
|
||||
public init() {
|
||||
let headingStyle = NSParagraphStyle()
|
||||
|
||||
let bodyStyle = NSMutableParagraphStyle()
|
||||
bodyStyle.paragraphSpacingBefore = 2
|
||||
bodyStyle.paragraphSpacing = 2
|
||||
bodyStyle.lineSpacing = 2
|
||||
|
||||
let codeStyle = NSMutableParagraphStyle()
|
||||
codeStyle.paragraphSpacingBefore = 2
|
||||
codeStyle.paragraphSpacing = 2
|
||||
|
||||
self.heading1 = headingStyle
|
||||
self.heading2 = headingStyle
|
||||
self.heading3 = headingStyle
|
||||
self.heading4 = headingStyle
|
||||
self.heading5 = headingStyle
|
||||
self.heading6 = headingStyle
|
||||
self.body = bodyStyle
|
||||
self.code = codeStyle
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ import Cocoa
|
||||
import RxSwift
|
||||
import PureLayout
|
||||
import CocoaFontAwesome
|
||||
import Commons
|
||||
|
||||
class FileBrowser: NSView,
|
||||
UiComponent {
|
||||
|
@ -9,82 +9,4 @@ import os
|
||||
extension URL {
|
||||
|
||||
var direntType: UInt8 { (self as NSURL).direntType() }
|
||||
|
||||
func isDirectParent(of url: URL) -> Bool {
|
||||
guard self.isFileURL && url.isFileURL else { return false }
|
||||
|
||||
let myPathComps = self.pathComponents
|
||||
let targetPathComps = url.pathComponents
|
||||
|
||||
guard targetPathComps.count == myPathComps.count + 1 else { return false }
|
||||
|
||||
return Array(targetPathComps[0..<myPathComps.count]) == myPathComps
|
||||
}
|
||||
|
||||
func isParent(of url: URL) -> Bool {
|
||||
guard self.isFileURL && url.isFileURL else { return false }
|
||||
|
||||
let myPathComps = self.pathComponents
|
||||
let targetPathComps = url.pathComponents
|
||||
|
||||
guard targetPathComps.count > myPathComps.count else { return false }
|
||||
|
||||
return Array(targetPathComps[0..<myPathComps.count]) == myPathComps
|
||||
}
|
||||
|
||||
func isContained(in parentUrl: URL) -> Bool {
|
||||
if parentUrl == self { return false }
|
||||
|
||||
let pathComps = self.pathComponents
|
||||
let parentPathComps = parentUrl.pathComponents
|
||||
|
||||
guard pathComps.count > parentPathComps.count else { return false }
|
||||
|
||||
guard Array(pathComps[0..<parentPathComps.endIndex]) == parentPathComps else { return false }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
var parent: URL {
|
||||
if self.path == "/" { return self }
|
||||
|
||||
return self.deletingLastPathComponent()
|
||||
}
|
||||
|
||||
var isDir: Bool { self.resourceValue(URLResourceKey.isDirectoryKey.rawValue) }
|
||||
|
||||
var isHidden: Bool { self.resourceValue(URLResourceKey.isHiddenKey.rawValue) }
|
||||
|
||||
var isPackage: Bool { self.resourceValue(URLResourceKey.isPackageKey.rawValue) }
|
||||
|
||||
/// Wrapper function for NSURL.getResourceValue for Bool values.
|
||||
/// Returns also `false` when
|
||||
/// - there is no value for the given `key` or
|
||||
/// - the value cannot be converted to `NSNumber`.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - key: The `key`-parameter of `NSURL.getResourceValue`.
|
||||
private func resourceValue(_ key: String) -> Bool {
|
||||
var rsrc: AnyObject?
|
||||
|
||||
do {
|
||||
try (self as NSURL).getResourceValue(&rsrc, forKey: URLResourceKey(rawValue: key))
|
||||
} catch let error as NSError {
|
||||
// FIXME error handling
|
||||
log.error("ERROR while getting \(key): \(error)")
|
||||
return false
|
||||
}
|
||||
|
||||
if let result = rsrc as? NSNumber { return result.boolValue }
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
extension ValueTransformer {
|
||||
|
||||
static var keyedUnarchiveFromDataTransformer
|
||||
= ValueTransformer(forName: .keyedUnarchiveFromDataTransformerName)!
|
||||
}
|
||||
|
||||
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.general)
|
||||
|
@ -16,12 +16,4 @@ class OpenQuicklyFileViewRow: NSTableRowView {
|
||||
|
||||
self.rectsBeingDrawn().forEach { NSIntersectionRect($0, dirtyRect).fill(using: .sourceOver) }
|
||||
}
|
||||
|
||||
private func rectsBeingDrawn() -> [CGRect] {
|
||||
var rectsPtr: UnsafePointer<CGRect>? = nil
|
||||
var count: Int = 0
|
||||
self.getRectsBeingDrawn(&rectsPtr, count: &count)
|
||||
|
||||
return Array(UnsafeBufferPointer(start: rectsPtr, count: count))
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import Cocoa
|
||||
import NvimView
|
||||
import Commons
|
||||
|
||||
func changeTheme(themePrefChanged: Bool, themeChanged: Bool, usesTheme: Bool,
|
||||
forTheme: () -> Void, forDefaultTheme: () -> Void) -> Bool {
|
||||
|
Loading…
Reference in New Issue
Block a user