Compare commits

..

No commits in common. "6b39e90ea4f4675d248668e8fce4c1c6f1f4a315" and "83cfba74a83fa530b3b81f7f7ef8b9cec9b4003c" have entirely different histories.

13 changed files with 125 additions and 742 deletions

View File

@ -13,10 +13,6 @@
D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */; }; D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */; };
D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62408C02438CF550020E09F /* JavaScriptEditorView.swift */; }; D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62408C02438CF550020E09F /* JavaScriptEditorView.swift */; };
D624090F243903E90020E09F /* ExtendedJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D624090E243903E90020E09F /* ExtendedJSON.swift */; }; D624090F243903E90020E09F /* ExtendedJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D624090E243903E90020E09F /* ExtendedJSON.swift */; };
D626BF82243BD2EE0075117B /* EditDocumentWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626BF80243BD2EE0075117B /* EditDocumentWindowController.swift */; };
D626BF83243BD2EE0075117B /* EditDocumentWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D626BF81243BD2EE0075117B /* EditDocumentWindowController.xib */; };
D626BF86243BE19A0075117B /* EditDocumentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626BF84243BE19A0075117B /* EditDocumentViewController.swift */; };
D626BF87243BE19A0075117B /* EditDocumentViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D626BF85243BE19A0075117B /* EditDocumentViewController.xib */; };
D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDEBD23C837DC0012D658 /* AppDelegate.swift */; }; D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDEBD23C837DC0012D658 /* AppDelegate.swift */; };
D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEBF23C837DD0012D658 /* Assets.xcassets */; }; D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEBF23C837DD0012D658 /* Assets.xcassets */; };
D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEC123C837DD0012D658 /* MainMenu.xib */; }; D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEC123C837DD0012D658 /* MainMenu.xib */; };
@ -92,10 +88,6 @@
D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ServerConnectViewController.xib; sourceTree = "<group>"; }; D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ServerConnectViewController.xib; sourceTree = "<group>"; };
D62408C02438CF550020E09F /* JavaScriptEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptEditorView.swift; sourceTree = "<group>"; }; D62408C02438CF550020E09F /* JavaScriptEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptEditorView.swift; sourceTree = "<group>"; };
D624090E243903E90020E09F /* ExtendedJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtendedJSON.swift; sourceTree = "<group>"; }; D624090E243903E90020E09F /* ExtendedJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtendedJSON.swift; sourceTree = "<group>"; };
D626BF80243BD2EE0075117B /* EditDocumentWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDocumentWindowController.swift; sourceTree = "<group>"; };
D626BF81243BD2EE0075117B /* EditDocumentWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditDocumentWindowController.xib; sourceTree = "<group>"; };
D626BF84243BE19A0075117B /* EditDocumentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDocumentViewController.swift; sourceTree = "<group>"; };
D626BF85243BE19A0075117B /* EditDocumentViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditDocumentViewController.xib; sourceTree = "<group>"; };
D63CDEBA23C837DC0012D658 /* MongoView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MongoView.app; sourceTree = BUILT_PRODUCTS_DIR; }; D63CDEBA23C837DC0012D658 /* MongoView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MongoView.app; sourceTree = BUILT_PRODUCTS_DIR; };
D63CDEBD23C837DC0012D658 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; D63CDEBD23C837DC0012D658 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
D63CDEBF23C837DD0012D658 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; D63CDEBF23C837DD0012D658 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@ -161,8 +153,6 @@
D60C863823CA2DD100C9DB8E /* ServerConnectWindowController.xib */, D60C863823CA2DD100C9DB8E /* ServerConnectWindowController.xib */,
D63CDF3A23C838470012D658 /* DatabaseWindowController.swift */, D63CDF3A23C838470012D658 /* DatabaseWindowController.swift */,
D63CDF3B23C838470012D658 /* DatabaseWindowController.xib */, D63CDF3B23C838470012D658 /* DatabaseWindowController.xib */,
D626BF80243BD2EE0075117B /* EditDocumentWindowController.swift */,
D626BF81243BD2EE0075117B /* EditDocumentWindowController.xib */,
); );
path = Windows; path = Windows;
sourceTree = "<group>"; sourceTree = "<group>";
@ -176,8 +166,6 @@
D63CDF4323C970C50012D658 /* DatabaseViewController.xib */, D63CDF4323C970C50012D658 /* DatabaseViewController.xib */,
D63CDF3E23C839010012D658 /* QueryViewController.swift */, D63CDF3E23C839010012D658 /* QueryViewController.swift */,
D63CDF3F23C839010012D658 /* QueryViewController.xib */, D63CDF3F23C839010012D658 /* QueryViewController.xib */,
D626BF84243BE19A0075117B /* EditDocumentViewController.swift */,
D626BF85243BE19A0075117B /* EditDocumentViewController.xib */,
); );
path = "View Controllers"; path = "View Controllers";
sourceTree = "<group>"; sourceTree = "<group>";
@ -346,12 +334,10 @@
D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */, D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */,
D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */, D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */,
D60C863A23CA2DD100C9DB8E /* ServerConnectWindowController.xib in Resources */, D60C863A23CA2DD100C9DB8E /* ServerConnectWindowController.xib in Resources */,
D626BF87243BE19A0075117B /* EditDocumentViewController.xib in Resources */,
D63CDF4523C970C50012D658 /* DatabaseViewController.xib in Resources */, D63CDF4523C970C50012D658 /* DatabaseViewController.xib in Resources */,
D6A7D09A243546B500B46857 /* WindowStatusView.xib in Resources */, D6A7D09A243546B500B46857 /* WindowStatusView.xib in Resources */,
D63CDF3D23C838470012D658 /* DatabaseWindowController.xib in Resources */, D63CDF3D23C838470012D658 /* DatabaseWindowController.xib in Resources */,
D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */, D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */,
D626BF83243BD2EE0075117B /* EditDocumentWindowController.xib in Resources */,
D63CDF4123C839010012D658 /* QueryViewController.xib in Resources */, D63CDF4123C839010012D658 /* QueryViewController.xib in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -369,12 +355,10 @@
D63CDF3823C8381A0012D658 /* MongoController.swift in Sources */, D63CDF3823C8381A0012D658 /* MongoController.swift in Sources */,
D60C863923CA2DD100C9DB8E /* ServerConnectWindowController.swift in Sources */, D60C863923CA2DD100C9DB8E /* ServerConnectWindowController.swift in Sources */,
D63CDF3723C8381A0012D658 /* Node.swift in Sources */, D63CDF3723C8381A0012D658 /* Node.swift in Sources */,
D626BF86243BE19A0075117B /* EditDocumentViewController.swift in Sources */,
D60C863F23CA2E2100C9DB8E /* ServerConnectViewController.swift in Sources */, D60C863F23CA2E2100C9DB8E /* ServerConnectViewController.swift in Sources */,
D63CDF4423C970C50012D658 /* DatabaseViewController.swift in Sources */, D63CDF4423C970C50012D658 /* DatabaseViewController.swift in Sources */,
D63CDF3C23C838470012D658 /* DatabaseWindowController.swift in Sources */, D63CDF3C23C838470012D658 /* DatabaseWindowController.swift in Sources */,
D6A7D096243541A400B46857 /* WindowStatusView.swift in Sources */, D6A7D096243541A400B46857 /* WindowStatusView.swift in Sources */,
D626BF82243BD2EE0075117B /* EditDocumentWindowController.swift in Sources */,
D6A7D0A42435885B00B46857 /* JavaScriptHighlighter.swift in Sources */, D6A7D0A42435885B00B46857 /* JavaScriptHighlighter.swift in Sources */,
D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */, D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */,
D63CDF4023C839010012D658 /* QueryViewController.swift in Sources */, D63CDF4023C839010012D658 /* QueryViewController.swift in Sources */,

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1140"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D63CDEB923C837DC0012D658"
BuildableName = "MongoView.app"
BlueprintName = "MongoView"
ReferencedContainer = "container:MongoView.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D63CDEB923C837DC0012D658"
BuildableName = "MongoView.app"
BlueprintName = "MongoView"
ReferencedContainer = "container:MongoView.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D63CDEB923C837DC0012D658"
BuildableName = "MongoView.app"
BlueprintName = "MongoView"
ReferencedContainer = "container:MongoView.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1140"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D6D13B002436C33D00493D97"
BuildableName = "jstest"
BlueprintName = "jstest"
ReferencedContainer = "container:MongoView.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D6D13B002436C33D00493D97"
BuildableName = "jstest"
BlueprintName = "jstest"
ReferencedContainer = "container:MongoView.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D6D13B002436C33D00493D97"
BuildableName = "jstest"
BlueprintName = "jstest"
ReferencedContainer = "container:MongoView.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -8,7 +8,6 @@
import Foundation import Foundation
import JavaScriptCore import JavaScriptCore
import MongoSwift
struct ExtendedJSON { struct ExtendedJSON {
private init() {} private init() {}
@ -26,27 +25,4 @@ struct ExtendedJSON {
return context.evaluateScript("JSON.stringify(\(string))")?.toString() return context.evaluateScript("JSON.stringify(\(string))")?.toString()
} }
private static func fromExtJSON(_ string: String) -> Document? {
do {
let doc = try Document(fromJSON: string)
return doc
} catch {
print("Unable to create document from extended JSON: \(error)")
return nil
}
}
static func toDocument(_ string: String) -> Document? {
guard let normalized = normalize(string),
let doc = fromExtJSON(normalized) else {
return nil
}
return doc
}
static func prettify(_ string: String) -> String? {
let command = "JSON.stringify(JSON.parse(`\(string)`), null, 4)"
return context.evaluateScript(command)?.toString()
}
} }

View File

@ -7,9 +7,6 @@
// //
import AppKit import AppKit
import OSLog
fileprivate let log = OSLog(subsystem: "space.vaccor.MongoView.JavaScriptHighlighter", category: .pointsOfInterest)
fileprivate let identifiers: CharacterSet = { fileprivate let identifiers: CharacterSet = {
var set = CharacterSet.alphanumerics var set = CharacterSet.alphanumerics
@ -25,30 +22,24 @@ fileprivate let operators = CharacterSet(charactersIn: "+-*/<>=")
fileprivate let expressionEnds = CharacterSet(charactersIn: ",]});") fileprivate let expressionEnds = CharacterSet(charactersIn: ",]});")
class JavaScriptHighlighter { class JavaScriptHighlighter {
private var text: String! private let text: String
private var attributed: NSMutableAttributedString! private var attributed: NSMutableAttributedString
private var currentIndex: String.Index! private var currentIndex: String.Index!
private var _indent = "" private var indent = ""
private(set) var tokens = [(token: TokenType, range: NSRange)]() private(set) var tokens = [(token: TokenType, range: NSRange)]()
var debug = false
private func print(_ str: @autoclosure () -> String) { init(text: String) {
#if DEBUG self.text = text
if debug { self.attributed = NSMutableAttributedString(attributedString: NSAttributedString(string: text))
Swift.print("\(_indent)\(str())")
}
#endif
} }
private func indent() { init(mutableAttributed: NSMutableAttributedString) {
#if DEBUG self.text = mutableAttributed.string
_indent += " " self.attributed = mutableAttributed
#endif
} }
private func outdent() {
#if DEBUG private func print(_ str: String) {
_indent = String(_indent.dropLast(2)) Swift.print("\(indent)\(str)")
#endif
} }
private func range(from: String.Index, to: String.Index) -> NSRange { private func range(from: String.Index, to: String.Index) -> NSRange {
@ -71,29 +62,14 @@ class JavaScriptHighlighter {
return text[currentIndex..<text.index(currentIndex, offsetBy: realLength)] return text[currentIndex..<text.index(currentIndex, offsetBy: realLength)]
} }
private func consume() { @discardableResult
currentIndex = text.index(after: currentIndex) private func consume() -> Unicode.Scalar? {
}
private func getAndConsume() -> Unicode.Scalar? {
let c = peek() let c = peek()
consume() currentIndex = text.index(after: currentIndex)
return c return c
} }
func highlight(text: String) { func highlight() {
self.highlight(attributed: NSMutableAttributedString(attributedString: NSAttributedString(string: text)))
}
func highlight(attributed: NSMutableAttributedString) {
self.attributed = attributed
self.text = attributed.string
self.tokens = []
os_signpost(.begin, log: log, name: "highlight")
defer { os_signpost(.end, log: log, name: "highlight") }
attributed.beginEditing()
let fullRange = NSRange(location: 0, length: attributed.length) let fullRange = NSRange(location: 0, length: attributed.length)
attributed.setAttributes([ attributed.setAttributes([
.foregroundColor: NSColor.textColor, .foregroundColor: NSColor.textColor,
@ -104,99 +80,21 @@ class JavaScriptHighlighter {
while let char = peek(), !expressionEnds.contains(char) { while let char = peek(), !expressionEnds.contains(char) {
consumeExpression() consumeExpression()
} }
attributed.endEditing()
}
func inserted(character: Unicode.Scalar, index: Int) -> Bool {
os_signpost(.begin, log: log, name: "inserted(character:index:)")
defer { os_signpost(.end, log: log, name: "inserted(character:index:)") }
if let (token, range) = tokenAndRange(fullyContaining: index) {
switch token {
case .identifier:
let set = range.location == index ? identifierStarts : identifiers
guard set.contains(character) else { return false }
case let .string(stringChar):
guard character != stringChar || (index > 0 && Unicode.Scalar((text as NSString).character(at: index - 1)) == "\\"),
character != "\\" else { return false }
case .number:
if character == "." && (attributed.string as NSString).substring(with: range).contains(Character(".")) {
return false
}
default:
return false
}
var attributes: [NSAttributedString.Key: Any] = [
.font: NSFont.monospacedSystemFont(ofSize: 13, weight: .regular)
]
if let color = token.color {
attributes[.foregroundColor] = color
}
attributed.addAttributes(attributes, range: NSRange(location: index, length: 1))
tokens = tokens.map { (token, range) in
if range.contains(index) {
return (token, NSRange(location: range.location, length: range.length + 1))
} else if range.location >= index {
return (token, NSRange(location: range.location + 1, length: range.length))
} else {
return (token, range)
}
}
return true
}
return false
}
func removed(index: Int) -> Bool {
os_signpost(.begin, log: log, name: "removed(at:)")
defer { os_signpost(.end, log: log, name: "removed(at:)") }
if let (token, range) = tokenAndRange(fullyContaining: index) {
switch token {
case .string(_):
guard index > range.location && index < range.location + range.length - 1 else { return false }
if index > 0 && Unicode.Scalar((text as NSString).character(at: index - 1)) == "\\" {
// removed character
return false
}
case .number:
break
default:
return false
}
tokens = tokens.map { (token, range) in
if range.contains(index) {
return (token, NSRange(location: range.location, length: range.length - 1))
} else if range.location >= index {
return (token, NSRange(location: range.location - 1, length: range.length))
} else {
return (token, range)
}
}
return true
}
return false
}
func token(at index: Int) -> TokenType? {
for (token, range) in tokens where range.contains(index) {
return token
}
return nil
}
private func tokenAndRange(fullyContaining index: Int) -> (TokenType, NSRange)? {
for (token, range) in tokens where index > range.location && index < range.location + range.length {
return (token, range)
}
return nil
} }
private func emit(token: TokenType, range: NSRange) { private func emit(token: TokenType, range: NSRange) {
if let color = token.color { let color: NSColor
attributed.addAttribute(.foregroundColor, value: color, range: range) switch token {
case .string:
color = .systemRed
case .number:
color = .systemBlue
case .punctuation:
color = .systemTeal
case .identifier:
return
} }
attributed.addAttribute(.foregroundColor, value: color, range: range)
tokens.append((token, range)) tokens.append((token, range))
} }
@ -225,8 +123,6 @@ class JavaScriptHighlighter {
consumeDotLookup() consumeDotLookup()
} else if char == "?" { } else if char == "?" {
consumeTernaryExpression() consumeTernaryExpression()
} else if expressionEnds.contains(char) {
return
} else { } else {
consume() consume()
} }
@ -266,20 +162,15 @@ class JavaScriptHighlighter {
private func consumeString() { private func consumeString() {
let stringStart = currentIndex! let stringStart = currentIndex!
let quote = peek()! let startChar = consume()
consume() // opening quote while currentIndex < text.endIndex && peek() != startChar && (currentIndex == text.startIndex || text[text.index(before: currentIndex)] != "\\") {
var prevChar: Unicode.Scalar?
var char = peek()
while currentIndex < text.endIndex {
consume() consume()
if char == quote && prevChar != "\\" {
break
} }
prevChar = char if currentIndex < text.endIndex {
char = peek() consume() // string closing quote
} }
print("String: \(text[stringStart..<currentIndex])") print("String: \(text[stringStart..<currentIndex])")
emit(token: .string(quote), range: range(from: stringStart, to: currentIndex)) emit(token: .string, range: range(from: stringStart, to: currentIndex))
} }
private func consumeTemplateString() { private func consumeTemplateString() {
@ -288,14 +179,14 @@ class JavaScriptHighlighter {
func emitTemplateStringFragment() { func emitTemplateStringFragment() {
guard stringFragmentStart != currentIndex else { return } guard stringFragmentStart != currentIndex else { return }
print("Template string fragment: '\(text[stringFragmentStart!..<currentIndex])'") print("Template string fragment: '\(text[stringFragmentStart!..<currentIndex])'")
emit(token: .string("`"), range: range(from: stringFragmentStart!, to: currentIndex)) emit(token: .string, range: range(from: stringFragmentStart!, to: currentIndex))
stringFragmentStart = currentIndex stringFragmentStart = currentIndex
} }
consume() // opening ` consume() // opening `
while let char = peek() { while currentIndex < text.endIndex {
if char == "$" { if peek() == "$" {
emitTemplateStringFragment() emitTemplateStringFragment()
consume() // $ consume() // $
if peek() == "{" { if peek() == "{" {
@ -308,7 +199,7 @@ class JavaScriptHighlighter {
} }
} }
} else if char == "`" { } else if peek() == "`" {
stringFragmentStart = stringFragmentStart ?? currentIndex stringFragmentStart = stringFragmentStart ?? currentIndex
consume() // ` consume() // `
emitTemplateStringFragment() emitTemplateStringFragment()
@ -324,11 +215,11 @@ class JavaScriptHighlighter {
} }
private func consumeTemplateStringExpression() { private func consumeTemplateStringExpression() {
indent() indent += " "
while currentIndex < text.endIndex && peek() != "}" { while currentIndex < text.endIndex && peek() != "}" {
consumeExpression() consumeExpression()
} }
outdent() indent = String(indent.dropLast(2))
} }
private func consumeOperator() { private func consumeOperator() {
@ -340,11 +231,11 @@ class JavaScriptHighlighter {
consume() // ( consume() // (
print("Opening (") print("Opening (")
emit(token: .punctuation, range: prevCharRange()) emit(token: .punctuation, range: prevCharRange())
indent() indent += " "
while currentIndex < text.endIndex && peek() != ")" { while currentIndex < text.endIndex && peek() != ")" {
consumeExpression() consumeExpression()
} }
outdent() indent = String(indent.dropLast(2))
if currentIndex < text.endIndex { if currentIndex < text.endIndex {
consume() // ) consume() // )
print("Closing )") print("Closing )")
@ -356,29 +247,34 @@ class JavaScriptHighlighter {
consume() // { consume() // {
print("Opening {") print("Opening {")
emit(token: .punctuation, range: prevCharRange()) emit(token: .punctuation, range: prevCharRange())
indent() indent += " "
while let char = peek() { object:
if char == "}" { while currentIndex < text.endIndex && peek() != "}" {
consume() // } consumeObjectKey()
print("Closing }") if peek() == ":" {
emit(token: .punctuation, range: prevCharRange())
break
} else if char == "'" || char == "\"" {
let keyStart = currentIndex!
consumeString()
print("Object key: '\(text[keyStart..<currentIndex])'")
} else if identifierStarts.contains(char) {
let keyStart = currentIndex!
consumeIdentifier()
print("Object key: '\(text[keyStart..<currentIndex])'")
} else if char == ":" || char == "," {
consume() // : consume() // :
emit(token: .punctuation, range: prevCharRange()) emit(token: .punctuation, range: prevCharRange())
} else { consumeWhitespace()
while currentIndex < text.endIndex && peek() != "," && peek() != "}" {
consumeExpression() consumeExpression()
} }
} }
outdent() consumeWhitespace()
if peek() == "," {
consume() // ,
emit(token: .punctuation, range: prevCharRange())
continue
} else {
break
}
}
indent = String(indent.dropLast(2))
if currentIndex < text.endIndex {
consume() // }
print("Closing }")
emit(token: .punctuation, range: prevCharRange())
}
} }
private func consumeObjectKey() { private func consumeObjectKey() {
@ -396,47 +292,46 @@ class JavaScriptHighlighter {
private func consumeDotLookup() { private func consumeDotLookup() {
consume() // . consume() // .
guard let char = peek() else { return }
if identifierStarts.contains(char) {
print("Dot lookup") print("Dot lookup")
emit(token: .punctuation, range: prevCharRange()) emit(token: .punctuation, range: prevCharRange())
consumeIdentifier()
} else if CharacterSet.decimalDigits.contains(char) {
let numberStart = text.index(before: currentIndex)
while let char = peek(), CharacterSet.decimalDigits.contains(char) {
consume()
}
print("Number: \(text[numberStart..<currentIndex])")
emit(token: .number, range: range(from: numberStart, to: currentIndex))
}
} }
private func consumeArray() { private func consumeArray() {
consume() // [ consume() // [
print("Opening [") print("Opening [")
emit(token: .punctuation, range: prevCharRange()) emit(token: .punctuation, range: prevCharRange())
indent() indent += " "
while let char = peek() { array:
if char == "]" { while currentIndex < text.endIndex && peek() != "]" {
consume() // ] consumeWhitespace()
print("Closing ]") while currentIndex < text.endIndex {
emit(token: .punctuation, range: prevCharRange()) if peek() == "," {
break
} else if char == "," {
consume() // , consume() // ,
print("Array separator") print("Array separator")
emit(token: .punctuation, range: prevCharRange()) emit(token: .punctuation, range: prevCharRange())
break
} else if peek() == "]" {
break array
} else { } else {
indent += " "
print("Array element")
consumeExpression() consumeExpression()
indent = String(indent.dropLast(2))
} }
} }
outdent() }
indent = String(indent.dropLast(2))
if currentIndex < text.endIndex {
consume() // ]
print("Closing ]")
emit(token: .punctuation, range: prevCharRange())
}
} }
func consumeTernaryExpression() { func consumeTernaryExpression() {
consume() // ? consume() // ?
print("Ternary expression") print("Ternary expression")
indent() indent += " "
print("Ternary true result") print("Ternary true result")
while let char = peek(), char != ":" { while let char = peek(), char != ":" {
consumeExpression() // true result consumeExpression() // true result
@ -446,7 +341,7 @@ class JavaScriptHighlighter {
while let char = peek(), !expressionEnds.contains(char) { while let char = peek(), !expressionEnds.contains(char) {
consumeExpression() consumeExpression()
} }
outdent() indent = String(indent.dropLast(2))
} }
} }
@ -456,19 +351,6 @@ extension JavaScriptHighlighter {
case identifier case identifier
case punctuation case punctuation
case number case number
case string(Unicode.Scalar) case string
var color: NSColor? {
switch self {
case .string(_):
return .systemRed
case .number:
return .systemBlue
case .punctuation:
return .systemTeal
case .identifier:
return nil
}
}
} }
} }

View File

@ -1,70 +0,0 @@
//
// EditDocumentViewController.swift
// MongoView
//
// Created by Shadowfacts on 4/6/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import Cocoa
import MongoSwift
class EditDocumentViewController: NSViewController {
private(set) var mongoController: MongoController!
private(set) var collection: DatabaseCollection!
private(set) var document: Document!
var documentEdited: (() -> Void)?
@IBOutlet var editorTextView: JavaScriptEditorView!
@IBOutlet weak var saveButton: NSButton!
@IBOutlet weak var cancelButton: NSButton!
@IBOutlet weak var validateButton: NSButton!
init(mongoController: MongoController, collection: DatabaseCollection, document: Document) {
self.mongoController = mongoController
self.collection = collection
self.document = document
super.init(nibName: "EditDocumentViewController", bundle: .main)
}
required init?(coder: NSCoder) {
fatalError()
}
override func viewDidLoad() {
super.viewDidLoad()
editorTextView.string = ExtendedJSON.prettify(document.extendedJSON) ?? document.extendedJSON
editorTextView.isAutomaticQuoteSubstitutionEnabled = false
}
@IBAction func savePressed(_ sender: Any) {
guard let id = document["_id"],
let newDoc = ExtendedJSON.toDocument(editorTextView.string) else {
// todo: error
return
}
let collection = mongoController.collection(self.collection)
collection.replaceOne(filter: ["_id": id], replacement: newDoc).whenComplete { (result) in
DispatchQueue.main.async {
switch result {
case .success(_):
self.documentEdited?()
case let .failure(error):
print("Unable to replace document: \(error)")
}
self.view.window!.close()
}
}
}
@IBAction func cancelPressed(_ sender: Any) {
view.window!.close()
}
@IBAction func validatePressed(_ sender: Any) {
}
}

View File

@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="EditDocumentViewController" customModule="MongoView" customModuleProvider="target">
<connections>
<outlet property="cancelButton" destination="5M7-Eo-LRQ" id="9iE-dG-Rvz"/>
<outlet property="editorTextView" destination="1aa-Vo-yPS" id="hip-Qi-9BH"/>
<outlet property="saveButton" destination="3aO-fI-F6G" id="hbc-f1-hAJ"/>
<outlet property="validateButton" destination="J9n-en-a5p" id="SoQ-HS-byg"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<stackView distribution="fill" orientation="horizontal" alignment="top" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xa0-UE-ywz">
<rect key="frame" x="273" y="8" width="199" height="21"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5M7-Eo-LRQ">
<rect key="frame" x="-6" y="-7" width="82" height="32"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="xeo-Kh-gMm">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="cancelPressed:" target="-2" id="bmf-UI-VmZ"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3aO-fI-F6G">
<rect key="frame" x="72" y="-7" width="133" height="32"/>
<buttonCell key="cell" type="push" title="Save and Close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="FgS-jM-BWn">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="savePressed:" target="-2" id="Blr-6P-WPb"/>
</connections>
</button>
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
<scrollView borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MlX-0S-w82">
<rect key="frame" x="8" y="37" width="464" height="227"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="egN-c7-XBK">
<rect key="frame" x="0.0" y="0.0" width="449" height="227"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" id="1aa-Vo-yPS" customClass="JavaScriptEditorView" customModule="MongoView" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="449" height="227"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="449" height="227"/>
<size key="maxSize" width="465" height="10000000"/>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="IwO-eE-cem">
<rect key="frame" x="-100" y="-100" width="225" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" horizontal="NO" id="IDr-mZ-kqd">
<rect key="frame" x="449" y="0.0" width="15" height="227"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="J9n-en-a5p">
<rect key="frame" x="2" y="1" width="89" height="32"/>
<buttonCell key="cell" type="push" title="Validate" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="J6T-UY-zPK">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="validatePressed:" target="-2" id="gVI-wh-rT2"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="MlX-0S-w82" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="8" id="BdG-le-KXB"/>
<constraint firstItem="J9n-en-a5p" firstAttribute="top" secondItem="MlX-0S-w82" secondAttribute="bottom" constant="8" id="FvY-Be-Tdx"/>
<constraint firstItem="J9n-en-a5p" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="8" id="HzC-6Y-gZG"/>
<constraint firstAttribute="bottom" secondItem="xa0-UE-ywz" secondAttribute="bottom" constant="8" id="Ssc-Oa-bTe"/>
<constraint firstItem="xa0-UE-ywz" firstAttribute="top" secondItem="MlX-0S-w82" secondAttribute="bottom" constant="8" id="Uga-ZA-1b4"/>
<constraint firstAttribute="trailing" secondItem="xa0-UE-ywz" secondAttribute="trailing" constant="8" id="i4O-th-zRP"/>
<constraint firstAttribute="bottom" secondItem="J9n-en-a5p" secondAttribute="bottom" constant="8" id="lZs-Qs-8gq"/>
<constraint firstItem="MlX-0S-w82" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="8" id="m99-4c-vcx"/>
<constraint firstAttribute="trailing" secondItem="MlX-0S-w82" secondAttribute="trailing" constant="8" id="rYV-TB-qaV"/>
</constraints>
<point key="canvasLocation" x="140" y="154"/>
</customView>
</objects>
</document>

View File

@ -50,6 +50,7 @@ class QueryViewController: NSViewController {
verticalSplitView.delegate = self verticalSplitView.delegate = self
verticalSplitView.setHoldingPriority(.defaultHigh, forSubviewAt: 0) verticalSplitView.setHoldingPriority(.defaultHigh, forSubviewAt: 0)
filterTextView.font = .monospacedSystemFont(ofSize: 13, weight: .regular)
filterTextView.isAutomaticQuoteSubstitutionEnabled = false filterTextView.isAutomaticQuoteSubstitutionEnabled = false
filterTextView.string = defaultFilter filterTextView.string = defaultFilter
@ -79,7 +80,8 @@ class QueryViewController: NSViewController {
let filterText = filterTextView.string.trimmingCharacters(in: .whitespacesAndNewlines) let filterText = filterTextView.string.trimmingCharacters(in: .whitespacesAndNewlines)
let filter: Document let filter: Document
if !filterText.isEmpty, if !filterText.isEmpty,
let doc = ExtendedJSON.toDocument(filterText) { let normalized = ExtendedJSON.normalize(filterText),
let doc = try? Document(fromJSON: normalized) {
filter = doc filter = doc
} else { } else {
filter = [:] filter = [:]
@ -161,24 +163,11 @@ class QueryViewController: NSViewController {
} }
} }
@IBAction func editDocument(_ sender: Any) {
guard let node = outlineView.item(atRow: outlineView.clickedRow) as? Node,
node.parent == nil,
case let .document(document) = node.value else {
return
}
let wc = EditDocumentWindowController(mongoController: mongoController, collection: collection, document: document)
wc.documentEdited = {
self.refresh()
}
wc.showWindow(nil)
}
} }
extension QueryViewController: NSMenuItemValidation { extension QueryViewController: NSMenuItemValidation {
func validateMenuItem(_ menuItem: NSMenuItem) -> Bool { func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
if menuItem.action == #selector(deleteNode(_:)) || menuItem.action == #selector(editDocument(_:)) { if menuItem.action == #selector(deleteNode(_:)) {
if outlineView.clickedRow != -1, let node = outlineView.item(atRow: outlineView.clickedRow) as? Node, node.parent == nil { if outlineView.clickedRow != -1, let node = outlineView.item(atRow: outlineView.clickedRow) as? Node, node.parent == nil {
return true return true
} else { } else {

View File

@ -1139,12 +1139,6 @@
</customView> </customView>
<menu id="nL5-kg-dty"> <menu id="nL5-kg-dty">
<items> <items>
<menuItem title="Edit Document" id="0gS-XH-YDt">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="editDocument:" target="-2" id="DP4-Tq-o5M"/>
</connections>
</menuItem>
<menuItem title="Delete" id="nn0-ZF-eDZ"> <menuItem title="Delete" id="nn0-ZF-eDZ">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
<connections> <connections>

View File

@ -10,30 +10,17 @@ import AppKit
class JavaScriptEditorView: NSTextView { class JavaScriptEditorView: NSTextView {
var highlighter = JavaScriptHighlighter() var highlighter: JavaScriptHighlighter?
private var isRehighlighting = false
override var string: String { override var string: String {
get { didSet {
super.string
}
set {
isRehighlighting = true
super.string = newValue
rehighlight() rehighlight()
} }
} }
func rehighlight() { func rehighlight() {
isRehighlighting = true highlighter = JavaScriptHighlighter(mutableAttributed: self.textStorage!)
highlighter.highlight(attributed: self.textStorage!) highlighter!.highlight()
isRehighlighting = false
}
override func awakeFromNib() {
super.awakeFromNib()
textStorage!.delegate = self
} }
override func shouldChangeText(in affectedCharRange: NSRange, replacementString: String?) -> Bool { override func shouldChangeText(in affectedCharRange: NSRange, replacementString: String?) -> Bool {
@ -51,11 +38,16 @@ class JavaScriptEditorView: NSTextView {
return true return true
} }
override func didChangeText() {
rehighlight()
super.didChangeText()
}
func tryAutocompleteCharacter(for range: NSRange, string inserted: String) -> Bool { func tryAutocompleteCharacter(for range: NSRange, string inserted: String) -> Bool {
if let end = autocompleteResultFor(string: inserted, in: range) { if let end = autocompleteResultFor(string: inserted, in: range) {
textStorage!.insert(NSAttributedString(string: "\(inserted)\(end)"), at: range.location) textStorage!.insert(NSAttributedString(string: "\(inserted)\(end)"), at: range.location)
rehighlight() didChangeText()
super.didChangeText()
setSelectedRange(NSRange(location: range.location + 1, length: 0)) setSelectedRange(NSRange(location: range.location + 1, length: 0))
return true return true
} else { } else {
@ -66,57 +58,28 @@ class JavaScriptEditorView: NSTextView {
private func autocompleteResultFor(string: String, in range: NSRange) -> String? { private func autocompleteResultFor(string: String, in range: NSRange) -> String? {
switch string { switch string {
case "'", "\"", "`": case "'", "\"", "`":
if case .string(_) = highlighter.token(at: range.location) { return token(at: range.location) != .string ? string : nil
return nil
} else {
return string
}
case "(": case "(":
if case .string(_) = highlighter.token(at: range.location) { return token(at: range.location) != .string ? ")" : nil
return nil
} else {
return ")"
}
case "[": case "[":
if case .string(_) = highlighter.token(at: range.location) { return token(at: range.location) != .string ? "]" : nil
return nil
} else {
return "]"
}
case "{": case "{":
var prevChar: Unicode.Scalar?
if range.location > 0 { if range.location > 0 {
let index = self.string.index(self.string.startIndex, offsetBy: range.location - 1) let index = self.string.index(self.string.startIndex, offsetBy: range.location - 1)
let prevChar = self.string.unicodeScalars[index] prevChar = self.string.unicodeScalars[index]
if prevChar == "$" {
return "}"
}
}
if case .string(_) = highlighter.token(at: range.location) {
return nil
} else {
return "}"
} }
return token(at: range.location) != .string || (prevChar == "$") ? "}" : nil
default: default:
return nil return nil
} }
} }
} private func token(at index: Int) -> JavaScriptHighlighter.TokenType? {
guard let highlighter = highlighter else { return nil }
extension JavaScriptEditorView: NSTextStorageDelegate { for (token, range) in highlighter.tokens where range.contains(index) {
func textStorage(_ textStorage: NSTextStorage, didProcessEditing editedMask: NSTextStorageEditActions, range editedRange: NSRange, changeInLength delta: Int) { return token
guard editedMask.contains(.editedCharacters), !isRehighlighting else { return }
if delta == 1 {
if let char = Unicode.Scalar((textStorage.string as NSString).character(at: editedRange.location)),
highlighter.inserted(character: char, index: editedRange.location) {
return
} }
} else if delta == -1 { return nil
if highlighter.removed(index: editedRange.location) {
return
}
}
rehighlight()
} }
} }

View File

@ -1,38 +0,0 @@
//
// EditDocumentWindowController.swift
// MongoView
//
// Created by Shadowfacts on 4/6/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import Cocoa
import MongoSwift
class EditDocumentWindowController: NSWindowController {
private(set) var mongoController: MongoController!
private(set) var collection: DatabaseCollection!
private(set) var mongoDocument: Document!
var documentEdited: (() -> Void)?
convenience init(mongoController: MongoController, collection: DatabaseCollection, document: Document) {
self.init(windowNibName: "EditDocumentWindowController")
self.mongoController = mongoController
self.collection = collection
self.mongoDocument = document
}
override func windowDidLoad() {
super.windowDidLoad()
window!.title = "Edit \(collection.database).\(collection.name) Document"
let vc = EditDocumentViewController(mongoController: mongoController, collection: collection, document: mongoDocument)
vc.documentEdited = documentEdited
contentViewController = vc
}
}

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="EditDocumentWindowController" customModule="MongoView" customModuleProvider="target">
<connections>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="documentWindow" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="931" y="526" width="1200" height="900"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<value key="minSize" type="size" width="900" height="600"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="1200" height="900"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="140" y="147"/>
</window>
</objects>
</document>

View File

@ -8,7 +8,6 @@
import Foundation import Foundation
let source = "[1 + 2, 3,]" let source = "`$foo ${blah} bar`"
let highlighter = JavaScriptHighlighter(text: source) _ = JavaScriptHighlighter(text: source).highlight()
highlighter.debug = true
highlighter.highlight()