1
1
mirror of https://github.com/github/semantic.git synced 2024-12-19 04:41:47 +03:00
semantic/prototype/doubt-difftool/main.swift

104 lines
2.9 KiB
Swift
Raw Normal View History

import Cocoa
import Doubt
2015-10-28 01:38:25 +03:00
import Prelude
2015-10-27 18:04:39 +03:00
2015-10-28 01:29:27 +03:00
func readFile(path: String) -> String? {
guard let data = try? NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) else { return nil }
return data as String?
}
typealias Term = Cofree<String, Range<Int>>
2015-10-28 01:37:34 +03:00
2015-10-28 21:38:17 +03:00
struct Info: Categorizable, CustomJSONConvertible, Equatable {
2015-10-28 21:22:07 +03:00
let range: Range<Int>
2015-10-28 21:22:55 +03:00
2015-10-28 21:27:52 +03:00
2015-10-28 21:38:17 +03:00
// MARK: Categorizable
2015-10-29 00:51:54 +03:00
let categories: Set<String>
2015-10-28 21:38:17 +03:00
2015-10-28 21:27:52 +03:00
// MARK: CustomJSONConvertible
var JSON: Doubt.JSON {
return [
2015-10-29 01:11:22 +03:00
"range": range.JSON,
2015-10-29 00:51:54 +03:00
"categories": Array(categories).JSON
2015-10-28 21:27:52 +03:00
]
}
2015-10-28 21:22:07 +03:00
}
2015-10-28 21:23:58 +03:00
func == (left: Info, right: Info) -> Bool {
2015-10-29 00:51:54 +03:00
return left.range == right.range && left.categories == right.categories
2015-10-28 21:23:58 +03:00
}
2015-10-28 01:37:59 +03:00
func termWithInput(string: String) -> Term? {
2015-10-27 18:04:18 +03:00
let document = ts_document_make()
2015-10-28 01:26:39 +03:00
defer { ts_document_free(document) }
2015-10-28 01:29:44 +03:00
return string.withCString {
ts_document_set_language(document, ts_language_javascript())
ts_document_set_input_string(document, $0)
ts_document_parse(document)
let root = ts_document_root_node(document)
2015-10-28 01:07:00 +03:00
struct E: ErrorType {}
2015-10-28 21:20:46 +03:00
return try? Cofree
.ana { node, category in
let count = node.namedChildren.count
2015-10-29 00:48:51 +03:00
guard count > 0 else { return Syntax.Leaf(category) }
2015-10-28 22:05:25 +03:00
switch category {
2015-10-29 00:48:51 +03:00
case "pair":
2015-10-28 23:20:39 +03:00
return try .Fixed(node.namedChildren.map {
($0, try $0.category(document))
2015-10-28 23:20:39 +03:00
})
2015-10-29 00:48:51 +03:00
case "object":
2015-10-28 23:18:38 +03:00
return try .Keyed(Dictionary(elements: node.namedChildren.map {
guard let range = $0.namedChildren.first?.range else { throw E() }
guard let name = String(string.utf16[String.UTF16View.Index(_offset: range.startIndex)..<String.UTF16View.Index(_offset: range.endIndex)]) else { throw E() }
2015-10-29 00:32:11 +03:00
return try (name, ($0, $0.category(document)))
2015-10-28 23:18:38 +03:00
}))
2015-10-28 22:05:25 +03:00
default:
2015-10-28 22:31:08 +03:00
return try .Indexed(node.namedChildren.map {
($0, try $0.category(document))
2015-10-28 22:05:25 +03:00
})
}
2015-10-29 00:48:51 +03:00
} (root, "program")
2015-10-28 21:20:46 +03:00
.map { node, category in
2015-10-29 00:36:29 +03:00
node.range
2015-10-28 01:10:17 +03:00
}
2015-10-28 01:29:44 +03:00
}
2015-10-28 01:26:39 +03:00
}
2015-10-28 01:10:17 +03:00
2015-10-28 01:26:39 +03:00
let arguments = BoundsCheckedArray(array: Process.arguments)
2015-10-28 01:53:48 +03:00
if let aString = arguments[1].flatMap(readFile), bString = arguments[2].flatMap(readFile), c = arguments[3], ui = arguments[4] {
2015-10-28 01:38:25 +03:00
if let a = termWithInput(aString), b = termWithInput(bString) {
let diff = Interpreter<Term>(equal: Term.equals(annotation: const(true), leaf: ==), comparable: const(true), cost: Free.sum(Patch.difference)).run(a, b)
2015-10-28 01:38:31 +03:00
let range: Range<Int> -> Doubt.JSON = {
2015-10-28 21:32:59 +03:00
[
$0.startIndex.JSON,
($0.endIndex - $0.startIndex).JSON,
2015-10-28 01:38:31 +03:00
]
}
let JSON: Doubt.JSON = [
"before": .String(aString),
"after": .String(bString),
"diff": diff.JSON(pure: { $0.JSON { $0.JSON(annotation: range, leaf: Doubt.JSON.String) } }, leaf: Doubt.JSON.String, annotation: {
2015-10-28 01:38:31 +03:00
[
"before": range($0),
"after": range($1),
2015-10-28 01:38:31 +03:00
]
}),
]
2015-10-28 01:39:11 +03:00
let data = JSON.serialize()
try data.writeToFile(c, options: .DataWritingAtomic)
2015-10-28 01:53:48 +03:00
let components = NSURLComponents()
components.scheme = "file"
components.path = ui
2015-10-28 01:56:53 +03:00
components.query = c
2015-10-28 01:53:48 +03:00
if let URL = components.URL {
NSWorkspace.sharedWorkspace().openURL(URL)
}
2015-10-28 01:38:25 +03:00
}
2015-10-27 18:04:18 +03:00
}