mirror of
https://github.com/github/semantic.git
synced 2024-12-18 12:21:57 +03:00
Merge remote-tracking branch 'origin/master' into line-numbers
This commit is contained in:
commit
26dd51eb49
@ -43,7 +43,6 @@
|
||||
D49FCBC81BBF2C4300C5E9C3 /* Algorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC71BBF2C4300C5E9C3 /* Algorithm.swift */; };
|
||||
D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; };
|
||||
D4AAE5401B5AE2D0004E581F /* RangeReplaceableCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */; };
|
||||
D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53A1B5AE2D0004E581F /* Operators.swift */; };
|
||||
D4AAE5471B5AE2D0004E581F /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53C1B5AE2D0004E581F /* Optional.swift */; };
|
||||
D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */; };
|
||||
D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53F1B5AE2D0004E581F /* Syntax.swift */; };
|
||||
@ -116,7 +115,6 @@
|
||||
D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D4AAE5141B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RangeReplaceableCollectionType.swift; sourceTree = "<group>"; };
|
||||
D4AAE53A1B5AE2D0004E581F /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
|
||||
D4AAE53C1B5AE2D0004E581F /* Optional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Optional.swift; sourceTree = "<group>"; };
|
||||
D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringLiteralConvertible.swift; sourceTree = "<group>"; };
|
||||
D4AAE53F1B5AE2D0004E581F /* Syntax.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Syntax.swift; sourceTree = "<group>"; };
|
||||
@ -199,7 +197,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */,
|
||||
D4AAE53A1B5AE2D0004E581F /* Operators.swift */,
|
||||
D4AAE53C1B5AE2D0004E581F /* Optional.swift */,
|
||||
D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */,
|
||||
D4AAE53F1B5AE2D0004E581F /* Syntax.swift */,
|
||||
@ -464,7 +461,6 @@
|
||||
D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */,
|
||||
D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */,
|
||||
D1F5FE211BDE9C450048BAE4 /* JSONLeaf.swift in Sources */,
|
||||
D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -618,6 +614,7 @@
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_DISABLE_SAFETY_CHECKS = YES;
|
||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
|
@ -64,7 +64,7 @@
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "--unified"
|
||||
isEnabled = "YES">
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "https://raw.githubusercontent.com/jquery/jquery/2.1.0/src/effects.js"
|
||||
@ -83,7 +83,7 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
debugDocumentVersioning = "NO">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
|
@ -17,29 +17,6 @@ public enum Algorithm<Term: CofreeType, Result> {
|
||||
|
||||
/// A recursive instantiation of `Operation`, unrolling another iteration of the recursive type.
|
||||
indirect case Roll(Operation<Algorithm, Term, Diff>)
|
||||
|
||||
public func analysis<C>(@noescape ifPure ifPure: Result -> C, @noescape ifRoll: Operation<Algorithm, Term, Diff> -> C) -> C {
|
||||
switch self {
|
||||
case let .Pure(b):
|
||||
return ifPure(b)
|
||||
case let .Roll(a):
|
||||
return ifRoll(a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Functor
|
||||
|
||||
public func map<Other>(transform: Result -> Other) -> Algorithm<Term, Other> {
|
||||
return analysis(ifPure: transform >>> Algorithm<Term, Other>.Pure, ifRoll: { .Roll($0.map { $0.map(transform) }) })
|
||||
}
|
||||
|
||||
|
||||
// MARK: Monad
|
||||
|
||||
public func flatMap<C>(transform: Result -> Algorithm<Term, C>) -> Algorithm<Term, C> {
|
||||
return analysis(ifPure: transform, ifRoll: { .Roll($0.map { $0.flatMap(transform) }) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,11 +121,11 @@ extension CofreeType {
|
||||
}
|
||||
|
||||
|
||||
/// Catamorphism over `TermType`s.
|
||||
/// Catamorphism over `CofreeType`s.
|
||||
///
|
||||
/// Folds the tree encoded by the receiver into a single value by recurring top-down through the tree, applying `transform` to leaves, then to branches, and so forth.
|
||||
public func cata<Result>(transform: (Annotation, Syntax<Result, Leaf>) -> Result) -> Result {
|
||||
return self |> (Self.eliminate >>> { ($0, $1.map { $0.cata(transform) }) } >>> transform)
|
||||
public func cata<Result>(transform: (Annotation, Syntax<Result, Leaf>) throws -> Result) rethrows -> Result {
|
||||
return try transform(extract, unwrap.map { try $0.cata(transform) })
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,15 +21,6 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
|
||||
}
|
||||
|
||||
|
||||
public func analysis<C>(@noescape ifPure ifPure: Value throws -> C, @noescape ifRoll: (Annotation, Syntax<Free, Leaf>) throws -> C) rethrows -> C {
|
||||
switch self {
|
||||
case let .Pure(b):
|
||||
return try ifPure(b)
|
||||
case let .Roll(s):
|
||||
return try ifRoll(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Reduce the receiver by iteration.
|
||||
///
|
||||
/// `Pure` values are simply unpacked. `Roll` values are mapped recursively, and then have `transform` applied to them.
|
||||
@ -57,9 +48,12 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
|
||||
///
|
||||
/// For a lucid, in-depth tutorial on recursion schemes, I recommend [Patrick Thomson](https://twitter.com/importantshock)’s _[An Introduction to Recursion Schemes](http://patrickthomson.ghost.io/an-introduction-to-recursion-schemes/)_ and _[Recursion Schemes, Part 2: A Mob of Morphisms](http://patrickthomson.ghost.io/recursion-schemes-part-2/)_.
|
||||
public func cata(@noescape transform: (Annotation, Syntax<Value, Leaf>) throws -> Value) rethrows -> Value {
|
||||
return try analysis(
|
||||
ifPure: id,
|
||||
ifRoll: { try transform($0, $1.map { try $0.cata(transform) }) })
|
||||
switch self {
|
||||
case let .Pure(a):
|
||||
return a
|
||||
case let .Roll(annotation, syntax):
|
||||
return try transform(annotation, syntax.map { try $0.cata(transform) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -88,14 +82,12 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
|
||||
// MARK: Functor
|
||||
|
||||
public func map<C>(@noescape transform: Value throws -> C) rethrows -> Free<Leaf, Annotation, C> {
|
||||
return try analysis(ifPure: { try .Pure(transform($0)) }, ifRoll: { try .Roll($0, $1.map { try $0.map(transform) }) })
|
||||
}
|
||||
|
||||
|
||||
// MARK: Monad
|
||||
|
||||
public func flatMap<C>(@noescape transform: Value throws -> Free<Leaf, Annotation, C>) rethrows -> Free<Leaf, Annotation, C> {
|
||||
return try analysis(ifPure: transform, ifRoll: { try .Roll($0, $1.map { try $0.flatMap(transform) }) })
|
||||
switch self {
|
||||
case let .Pure(a):
|
||||
return try .Pure(transform(a))
|
||||
case let .Roll(annotation, syntax):
|
||||
return try .Roll(annotation, syntax.map { try $0.map(transform) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -216,14 +208,17 @@ public func == <Term: CofreeType, Annotation where Term.Leaf: Equatable> (left:
|
||||
|
||||
extension Free {
|
||||
public func JSON(pure pure: Value -> Doubt.JSON, leaf: Leaf -> Doubt.JSON, annotation: Annotation -> Doubt.JSON) -> Doubt.JSON {
|
||||
return analysis(
|
||||
ifPure: { [ "pure": pure($0) ] },
|
||||
ifRoll: {
|
||||
[ "roll": [
|
||||
"extract": annotation($0),
|
||||
"unwrap": $1.JSON(leaf: leaf, recur: { $0.JSON(pure: pure, leaf: leaf, annotation: annotation) })
|
||||
] ]
|
||||
})
|
||||
switch self {
|
||||
case let .Pure(a):
|
||||
return [ "pure": pure(a) ]
|
||||
case let .Roll(a, b):
|
||||
return [
|
||||
"roll": [
|
||||
"extract": annotation(a),
|
||||
"unwrap": b.JSON(leaf: leaf, recur: { $0.JSON(pure: pure, leaf: leaf, annotation: annotation) })
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
infix operator <> {
|
||||
associativity right
|
||||
precedence 140
|
||||
}
|
||||
|
||||
infix operator <+> {
|
||||
associativity right
|
||||
precedence 140
|
||||
}
|
||||
|
||||
infix operator </> {
|
||||
associativity right
|
||||
precedence 140
|
||||
}
|
||||
|
||||
infix operator >>> {
|
||||
associativity right
|
||||
precedence 170
|
||||
}
|
@ -48,8 +48,8 @@ public enum Syntax<Recur, A>: CustomDebugStringConvertible {
|
||||
/// Hylomorphisms are used to construct diffs corresponding to equal terms; see also `CofreeType.zip`.
|
||||
///
|
||||
/// `hylo` can be used with arbitrary functors which can eliminate to and introduce with `Syntax` values.
|
||||
public func hylo<A, B, Leaf>(down: Syntax<B, Leaf> -> B, _ up: A -> Syntax<A, Leaf>) -> A -> B {
|
||||
return up >>> { $0.map(hylo(down, up)) } >>> down
|
||||
public func hylo<A, B, Leaf>(down: Syntax<B, Leaf> -> B, _ up: A -> Syntax<A, Leaf>)(_ a: A) -> B {
|
||||
return down(up(a).map(hylo(down, up)))
|
||||
}
|
||||
|
||||
/// Reiteration through `Syntax`.
|
||||
@ -59,8 +59,9 @@ public func hylo<A, B, Leaf>(down: Syntax<B, Leaf> -> B, _ up: A -> Syntax<A, Le
|
||||
/// Hylomorphisms are used to construct diffs corresponding to equal terms; see also `CofreeType.zip`.
|
||||
///
|
||||
/// `hylo` can be used with arbitrary functors which can eliminate to and introduce with `Annotation` & `Syntax` pairs.
|
||||
public func hylo<A, B, Leaf, Annotation>(down: (Annotation, Syntax<B, Leaf>) -> B, _ up: A -> (Annotation, Syntax<A, Leaf>)) -> A -> B {
|
||||
return up >>> { ($0, $1.map(hylo(down, up))) } >>> down
|
||||
public func hylo<A, B, Leaf, Annotation>(down: (Annotation, Syntax<B, Leaf>) -> B, _ up: A -> (Annotation, Syntax<A, Leaf>))(_ a: A) -> B {
|
||||
let (annotation, syntax) = up(a)
|
||||
return down(annotation, syntax.map(hylo(down, up)))
|
||||
}
|
||||
|
||||
|
||||
@ -89,12 +90,12 @@ extension Syntax {
|
||||
switch (left, right) {
|
||||
case let (.Leaf(l1), .Leaf(l2)):
|
||||
return leaf(l1, l2)
|
||||
case let (.Indexed(v1), .Indexed(v2)):
|
||||
return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 }
|
||||
case let (.Fixed(v1), .Fixed(v2)):
|
||||
return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 }
|
||||
case let (.Keyed(d1), .Keyed(d2)):
|
||||
return Set(d1.keys) == Set(d2.keys) && d1.keys.map { recur(d1[$0]!, d2[$0]!) }.reduce(true) { $0 && $1 }
|
||||
case let (.Indexed(v1), .Indexed(v2)) where v1.count == v2.count:
|
||||
return zip(v1, v2).reduce(true) { $0 && recur($1) }
|
||||
case let (.Fixed(v1), .Fixed(v2)) where v1.count == v2.count:
|
||||
return zip(v1, v2).reduce(true) { $0 && recur($1) }
|
||||
case let (.Keyed(d1), .Keyed(d2)) where Set(d1.keys) == Set(d2.keys):
|
||||
return d1.keys.reduce(true) { $0 && recur(d1[$1]!, d2[$1]!) }
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
@ -14,15 +14,15 @@ extension TermType {
|
||||
/// Catamorphism over `TermType`s.
|
||||
///
|
||||
/// Folds the tree encoded by the receiver into a single value by recurring top-down through the tree, applying `transform` to leaves, then to branches, and so forth.
|
||||
public func cata<Result>(transform: Syntax<Result, Leaf> -> Result) -> Result {
|
||||
return self |> (Self.unwrap >>> { $0.map { $0.cata(transform) } } >>> transform)
|
||||
public func cata<Result>(transform: Syntax<Result, Leaf> throws -> Result) rethrows -> Result {
|
||||
return try transform(unwrap.map { try $0.cata(transform) })
|
||||
}
|
||||
|
||||
/// Paramorphism over `TermType`s.
|
||||
///
|
||||
/// Folds the tree encoded by the receiver into a single value by recurring top-down through the tree, applying `transform` to leaves, then to branches, and so forth. Each recursive instance is made available in the `Syntax` alongside the result value at that node.
|
||||
public func para<Result>(transform: Syntax<(Self, Result), Leaf> -> Result) -> Result {
|
||||
return self |> (Self.unwrap >>> { $0.map { ($0, $0.para(transform)) } } >>> transform)
|
||||
public func para<Result>(transform: Syntax<(Self, Result), Leaf> throws -> Result) rethrows -> Result {
|
||||
return try transform(unwrap.map { try ($0, $0.para(transform)) })
|
||||
}
|
||||
|
||||
|
||||
|
55
prototype/UI/diff.js
vendored
55
prototype/UI/diff.js
vendored
@ -67,10 +67,12 @@ function wrap(tagName, element) {
|
||||
}
|
||||
|
||||
/// String -> Syntax a -> Range -> (a -> Range) -> (a -> DOM) -> DOM
|
||||
function rangeAndSyntaxToDOM(source, syntax, range, getRange, recur) {
|
||||
function termToDOM(source, syntax, extract, getRange, recur) {
|
||||
recur = recur || function(term) {
|
||||
return rangeAndSyntaxToDOM(source, term.unwrap, term.extract, getRange);
|
||||
return termToDOM(source, term.unwrap, term.extract, getRange);
|
||||
}
|
||||
var categories = extract.categories;
|
||||
var range = extract.range;
|
||||
var element;
|
||||
if (syntax.leaf != null) {
|
||||
element = document.createElement("span");
|
||||
@ -83,18 +85,9 @@ function rangeAndSyntaxToDOM(source, syntax, range, getRange, recur) {
|
||||
var child = values[i];
|
||||
if (child.pure == "") continue;
|
||||
var childRange = getRange(child);
|
||||
if (childRange.before != null) {
|
||||
var beforeRange = childRange.before;
|
||||
element.appendChild(document.createTextNode(source.substr(previous, beforeRange[0] - previous)));
|
||||
element.appendChild(wrap("li", recur(child)));
|
||||
previous = beforeRange[0] + beforeRange[1];
|
||||
}
|
||||
if (childRange.after != null) {
|
||||
var afterRange = childRange.before;
|
||||
element.appendChild(document.createTextNode(source.substr(previous, afterRange[0] - previous)));
|
||||
element.appendChild(wrap("td", recur(child)));
|
||||
previous = afterRange[0] + afterRange[1];
|
||||
}
|
||||
element.appendChild(document.createTextNode(source.substr(previous, childRange[0] - previous)));
|
||||
element.appendChild(wrap("li", recur(child)));
|
||||
previous = childRange[0] + childRange[1];
|
||||
}
|
||||
element.appendChild(document.createTextNode(source.substr(previous, range[0] + range[1] - previous)));
|
||||
} else if (syntax.keyed != null) {
|
||||
@ -127,6 +120,11 @@ function rangeAndSyntaxToDOM(source, syntax, range, getRange, recur) {
|
||||
element.appendChild(document.createTextNode(source.substr(previous, range[0] + range[1] - previous)));
|
||||
}
|
||||
element["data-range"] = range;
|
||||
|
||||
for (index in categories) {
|
||||
element.classList.add('category-'+categories[index]);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@ -137,11 +135,11 @@ function diffToDOM(diff, sources) {
|
||||
if (diffOrTerm.pure != null) {
|
||||
var beforeRange, afterRange;
|
||||
if (diffOrTerm.pure.before != null) {
|
||||
beforeRange = diffOrTerm.pure.before.extract
|
||||
beforeRange = diffOrTerm.pure.before.extract.range
|
||||
}
|
||||
|
||||
if (diffOrTerm.pure.after != null) {
|
||||
afterRange = diffOrTerm.pure.after.extract
|
||||
afterRange = diffOrTerm.pure.after.extract.range
|
||||
}
|
||||
|
||||
if (beforeRange == null) {
|
||||
@ -154,10 +152,10 @@ function diffToDOM(diff, sources) {
|
||||
return { "before": beforeRange, "after": afterRange };
|
||||
}
|
||||
if (diffOrTerm.roll != null) {
|
||||
return diffOrTerm.roll.extract;
|
||||
return { before: diffOrTerm.roll.extract.before.range, after: diffOrTerm.roll.extract.after.range };
|
||||
}
|
||||
if (diffOrTerm.extract != null) {
|
||||
return diffOrTerm.extract;
|
||||
return diffOrTerm.extract.range;
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +173,7 @@ function diffToDOM(diff, sources) {
|
||||
function pureToDOM(sources, patch, getRangeFun, diffToDOMFun) {
|
||||
var elementA, elementB;
|
||||
if (patch.before != null) {
|
||||
elementA = rangeAndSyntaxToDOM(sources.before, patch.before.unwrap, patch.before.extract, getRangeFun);
|
||||
elementA = termToDOM(sources.before, patch.before.unwrap, patch.before.extract, getRangeFun);
|
||||
elementA.classList.add("delete");
|
||||
if (patch.after != null) {
|
||||
elementA.classList.add("replace");
|
||||
@ -183,7 +181,7 @@ function pureToDOM(sources, patch, getRangeFun, diffToDOMFun) {
|
||||
}
|
||||
|
||||
if (patch.after != null) {
|
||||
elementB = rangeAndSyntaxToDOM(sources.after, patch.after.unwrap, patch.after.extract, getRangeFun);
|
||||
elementB = termToDOM(sources.after, patch.after.unwrap, patch.after.extract, getRangeFun);
|
||||
elementB.classList.add("insert");
|
||||
if (patch.before != null) {
|
||||
elementB.classList.add("replace");
|
||||
@ -205,7 +203,14 @@ function pureToDOM(sources, patch, getRangeFun, diffToDOMFun) {
|
||||
|
||||
function rollToDOM(sources, rollOrTerm, getRangeFun, diffToDOMFun) {
|
||||
var syntax = rollOrTerm.unwrap
|
||||
var range = rollOrTerm.extract
|
||||
var categories = {
|
||||
before: rollOrTerm.extract.before.categories,
|
||||
after: rollOrTerm.extract.after.categories
|
||||
}
|
||||
var range = {
|
||||
before: rollOrTerm.extract.before.range,
|
||||
after: rollOrTerm.extract.after.range
|
||||
}
|
||||
|
||||
var elementA;
|
||||
var elementB;
|
||||
@ -429,6 +434,14 @@ function rollToDOM(sources, rollOrTerm, getRangeFun, diffToDOMFun) {
|
||||
elementB.appendChild(document.createTextNode(textB));
|
||||
}
|
||||
|
||||
for (index in categories.before) {
|
||||
elementA.classList.add('category-'+categories.before[index]);
|
||||
}
|
||||
|
||||
for (index in categories.after) {
|
||||
elementB.classList.add('category-'+categories.after[index]);
|
||||
}
|
||||
|
||||
return { "before": elementA, "after": elementB }
|
||||
}
|
||||
|
||||
|
0
prototype/UI/dom.js
vendored
0
prototype/UI/dom.js
vendored
@ -29,25 +29,69 @@
|
||||
background-color: #ffffec;
|
||||
outline: 1px solid #e9e9c0;
|
||||
}
|
||||
.invisible {
|
||||
background-color: #fff;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
background-color: #fff;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.diff div, .diff ul, .diff li, .diff dl, .diff dd, .diff span {
|
||||
white-space: pre-wrap;
|
||||
display: inline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: initial;
|
||||
}
|
||||
|
||||
.diff dt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* syntax highlighting */
|
||||
.diff .category-regex,
|
||||
.diff .category-string {
|
||||
color: #183691;
|
||||
}
|
||||
|
||||
.diff .category-false,
|
||||
.diff .category-true,
|
||||
.diff .category-null,
|
||||
.diff .category-undefined,
|
||||
.diff .category-number,
|
||||
.diff .category-function_call>li>.category-identifier,
|
||||
.diff .category-function_call>li>.category-member_access>.category-identifier,
|
||||
.diff .category-member_access>:not(:first-child)>.category-identifier {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.diff .category-comment {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.diff [class^="category-"][class$="_op"],
|
||||
.diff .category-ternary,
|
||||
.diff .category-var_declaration,
|
||||
.diff .category-new_expression,
|
||||
.diff .category-if_statement,
|
||||
.diff .category-do_statement,
|
||||
.diff .category-for_statement,
|
||||
.diff .category-for_in_statement,
|
||||
.diff .category-return_statement,
|
||||
.diff .category-function,
|
||||
.diff .category-assignment,
|
||||
.diff .category-var_assignment {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.diff .category-function>li:first-child>.category-identifier,
|
||||
.diff .category-new_expression>li>.category-function_call>li:first-child>.category-identifier,
|
||||
.diff .category-pair>li:first-child>.category-identifier,
|
||||
.diff .category-assignment>li:first-child>.category-member_access>:not(:first-child)>.category-identifier {
|
||||
color: #795da3;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="dictionary.js"></script>
|
||||
<script type="text/javascript" src="diff.js"></script>
|
||||
<script type="text/javascript" src="dom.js"></script>
|
||||
<script type="text/javascript" src="patch.js"></script>
|
||||
<script type="text/javascript" src="syntax.js"></script>
|
||||
<script type="text/javascript" src="term.js"></script>
|
||||
@ -66,16 +110,15 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="before" class="diff"></div>
|
||||
<div id="after" class="diff"></div>
|
||||
<div id="before" class="diff"></div>
|
||||
<div id="after" class="diff"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
loadJSON((window.location.search || '?diff.json').substr(1), function (json) {
|
||||
var diff = diffFromJSON(json.diff);
|
||||
|
||||
var dom = diffToDOM(diff, { "before": json["before"] , "after": json["after"] })
|
||||
document.getElementById("before").appendChild(dom.before);
|
||||
document.getElementById("after").appendChild(dom.after);
|
||||
var dom = diffToDOM(diff, { "before": json["before"] , "after": json["after"] })
|
||||
document.getElementById("before").appendChild(dom.before);
|
||||
document.getElementById("after").appendChild(dom.after);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
9
prototype/UI/term.js
vendored
9
prototype/UI/term.js
vendored
@ -12,12 +12,3 @@ function Term(object) {
|
||||
this.unwrap = object.unwrap;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Term -> String -> DOM
|
||||
function termToDOM(term, which, source) {
|
||||
return rangeAndSyntaxToDOM(term.range, term.unwrap, source, function(term) {
|
||||
return term.range;
|
||||
}, function(term) {
|
||||
return termToDOM(term, which, source);
|
||||
});
|
||||
}
|
||||
|
@ -26,20 +26,20 @@ extension TSNode {
|
||||
var namedChildren: ChildrenCollection {
|
||||
return ChildrenCollection(node: self, count: ts_node_named_child_count(self), child: ts_node_named_child)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct ChildrenCollection: CollectionType {
|
||||
let node: TSNode
|
||||
let count: Int
|
||||
let child: (TSNode, Int) -> TSNode
|
||||
struct ChildrenCollection: CollectionType {
|
||||
let node: TSNode
|
||||
let count: Int
|
||||
let child: (TSNode, Int) -> TSNode
|
||||
|
||||
subscript (index: Int) -> TSNode {
|
||||
return child(node, index)
|
||||
}
|
||||
subscript (index: Int) -> TSNode {
|
||||
return child(node, index)
|
||||
}
|
||||
|
||||
let startIndex = 0
|
||||
var endIndex: Int {
|
||||
return count
|
||||
}
|
||||
let startIndex = 0
|
||||
var endIndex: Int {
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ import Doubt
|
||||
import Prelude
|
||||
import Madness
|
||||
|
||||
func benchmark<T>(label: String? = nil, _ f: () -> T) -> T {
|
||||
func benchmark<T>(label: String? = nil, _ f: () throws -> T) rethrows -> T {
|
||||
let start = NSDate.timeIntervalSinceReferenceDate()
|
||||
let result = f()
|
||||
let result = try f()
|
||||
let end = NSDate.timeIntervalSinceReferenceDate()
|
||||
print((label.map { "\($0): " } ?? "") + "\(end - start)s")
|
||||
return result
|
||||
@ -144,7 +144,7 @@ func parserForType(type: String) -> String throws -> Term {
|
||||
}
|
||||
}
|
||||
|
||||
let parsed = parse(argumentsParser, input: Process.arguments)
|
||||
let parsed = benchmark("parsing arguments & loading sources") { parse(argumentsParser, input: Process.arguments) }
|
||||
let arguments: Argument = try parsed.either(ifLeft: { throw "\($0)" }, ifRight: { $0 })
|
||||
let (aSource, bSource) = arguments.sources
|
||||
let jsonURL = NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).URLByAppendingPathComponent("diff.json")
|
||||
@ -152,18 +152,18 @@ guard let uiPath = NSBundle.mainBundle().infoDictionary?["PathToUISource"] as? S
|
||||
guard aSource.type == bSource.type else { throw "can’t compare files of different types" }
|
||||
let parser = parserForType(aSource.type)
|
||||
|
||||
let a = try parser(aSource.contents)
|
||||
let b = try parser(bSource.contents)
|
||||
let diff = Interpreter<Term>(equal: Term.equals(annotation: const(true), leaf: ==), comparable: Interpreter<Term>.comparable { $0.extract.categories }, cost: Free.sum(Patch.sum)).run(a, b)
|
||||
let a = try benchmark("parsing source a") { try parser(aSource.contents) }
|
||||
let b = try benchmark("parsing source b") { try parser(bSource.contents) }
|
||||
let diff = benchmark("diffing") { Interpreter<Term>(equal: Term.equals(annotation: const(true), leaf: ==), comparable: Interpreter<Term>.comparable { $0.extract.categories }, cost: Free.sum(Patch.sum)).run(a, b) }
|
||||
switch arguments.output {
|
||||
case .Split:
|
||||
let JSON: Doubt.JSON = [
|
||||
"before": .String(aSource.contents),
|
||||
"after": .String(bSource.contents),
|
||||
"diff": diff.JSON(pure: { $0.JSON { $0.JSON(annotation: { $0.range.JSON }, leaf: Doubt.JSON.String) } }, leaf: Doubt.JSON.String, annotation: {
|
||||
"diff": diff.JSON(pure: { $0.JSON { $0.JSON(annotation: { $0.JSON }, leaf: Doubt.JSON.String) } }, leaf: Doubt.JSON.String, annotation: {
|
||||
[
|
||||
"before": $0.range.JSON,
|
||||
"after": $1.range.JSON,
|
||||
"before": $0.JSON,
|
||||
"after": $1.JSON,
|
||||
]
|
||||
}),
|
||||
]
|
||||
@ -178,5 +178,5 @@ case .Split:
|
||||
NSWorkspace.sharedWorkspace().openURL(URL)
|
||||
}
|
||||
case .Unified:
|
||||
print(benchmark { unified(diff, before: aSource.contents, after: bSource.contents) })
|
||||
print(benchmark("formatting unified diff") { unified(diff, before: aSource.contents, after: bSource.contents) })
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user