1
1
mirror of https://github.com/github/semantic.git synced 2024-12-18 20:31:55 +03:00

Merge remote-tracking branch 'origin/master' into line-numbers

This commit is contained in:
joshvera 2015-11-04 12:34:59 -05:00
commit 26dd51eb49
14 changed files with 153 additions and 155 deletions

View File

@ -43,7 +43,6 @@
D49FCBC81BBF2C4300C5E9C3 /* Algorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC71BBF2C4300C5E9C3 /* Algorithm.swift */; }; D49FCBC81BBF2C4300C5E9C3 /* Algorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC71BBF2C4300C5E9C3 /* Algorithm.swift */; };
D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; };
D4AAE5401B5AE2D0004E581F /* RangeReplaceableCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */; }; 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 */; }; D4AAE5471B5AE2D0004E581F /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53C1B5AE2D0004E581F /* Optional.swift */; };
D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */; }; D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */; };
D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53F1B5AE2D0004E581F /* Syntax.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; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; D4AAE53F1B5AE2D0004E581F /* Syntax.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Syntax.swift; sourceTree = "<group>"; };
@ -199,7 +197,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */, D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */,
D4AAE53A1B5AE2D0004E581F /* Operators.swift */,
D4AAE53C1B5AE2D0004E581F /* Optional.swift */, D4AAE53C1B5AE2D0004E581F /* Optional.swift */,
D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */, D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */,
D4AAE53F1B5AE2D0004E581F /* Syntax.swift */, D4AAE53F1B5AE2D0004E581F /* Syntax.swift */,
@ -464,7 +461,6 @@
D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */,
D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */, D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */,
D1F5FE211BDE9C450048BAE4 /* JSONLeaf.swift in Sources */, D1F5FE211BDE9C450048BAE4 /* JSONLeaf.swift in Sources */,
D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -618,6 +614,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.10; MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_DISABLE_SAFETY_CHECKS = YES;
SWIFT_INSTALL_OBJC_HEADER = NO; SWIFT_INSTALL_OBJC_HEADER = NO;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";

View File

@ -64,7 +64,7 @@
<CommandLineArguments> <CommandLineArguments>
<CommandLineArgument <CommandLineArgument
argument = "--unified" argument = "--unified"
isEnabled = "YES"> isEnabled = "NO">
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "https://raw.githubusercontent.com/jquery/jquery/2.1.0/src/effects.js" argument = "https://raw.githubusercontent.com/jquery/jquery/2.1.0/src/effects.js"
@ -83,7 +83,7 @@
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "NO">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">
<BuildableReference <BuildableReference

View File

@ -17,29 +17,6 @@ public enum Algorithm<Term: CofreeType, Result> {
/// A recursive instantiation of `Operation`, unrolling another iteration of the recursive type. /// A recursive instantiation of `Operation`, unrolling another iteration of the recursive type.
indirect case Roll(Operation<Algorithm, Term, Diff>) 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) }) })
}
} }

View File

@ -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. /// 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 { public func cata<Result>(transform: (Annotation, Syntax<Result, Leaf>) throws -> Result) rethrows -> Result {
return self |> (Self.eliminate >>> { ($0, $1.map { $0.cata(transform) }) } >>> transform) return try transform(extract, unwrap.map { try $0.cata(transform) })
} }

View File

@ -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. /// Reduce the receiver by iteration.
/// ///
/// `Pure` values are simply unpacked. `Roll` values are mapped recursively, and then have `transform` applied to them. /// `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/)_. /// 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 { public func cata(@noescape transform: (Annotation, Syntax<Value, Leaf>) throws -> Value) rethrows -> Value {
return try analysis( switch self {
ifPure: id, case let .Pure(a):
ifRoll: { try transform($0, $1.map { try $0.cata(transform) }) }) 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 // MARK: Functor
public func map<C>(@noescape transform: Value throws -> C) rethrows -> Free<Leaf, Annotation, C> { 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) }) }) switch self {
} case let .Pure(a):
return try .Pure(transform(a))
case let .Roll(annotation, syntax):
// MARK: Monad return try .Roll(annotation, syntax.map { try $0.map(transform) })
}
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) }) })
} }
@ -216,14 +208,17 @@ public func == <Term: CofreeType, Annotation where Term.Leaf: Equatable> (left:
extension Free { extension Free {
public func JSON(pure pure: Value -> Doubt.JSON, leaf: Leaf -> Doubt.JSON, annotation: Annotation -> Doubt.JSON) -> Doubt.JSON { public func JSON(pure pure: Value -> Doubt.JSON, leaf: Leaf -> Doubt.JSON, annotation: Annotation -> Doubt.JSON) -> Doubt.JSON {
return analysis( switch self {
ifPure: { [ "pure": pure($0) ] }, case let .Pure(a):
ifRoll: { return [ "pure": pure(a) ]
[ "roll": [ case let .Roll(a, b):
"extract": annotation($0), return [
"unwrap": $1.JSON(leaf: leaf, recur: { $0.JSON(pure: pure, leaf: leaf, annotation: annotation) }) "roll": [
] ] "extract": annotation(a),
}) "unwrap": b.JSON(leaf: leaf, recur: { $0.JSON(pure: pure, leaf: leaf, annotation: annotation) })
]
]
}
} }
} }

View File

@ -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
}

View File

@ -48,8 +48,8 @@ public enum Syntax<Recur, A>: CustomDebugStringConvertible {
/// Hylomorphisms are used to construct diffs corresponding to equal terms; see also `CofreeType.zip`. /// 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. /// `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 { public func hylo<A, B, Leaf>(down: Syntax<B, Leaf> -> B, _ up: A -> Syntax<A, Leaf>)(_ a: A) -> B {
return up >>> { $0.map(hylo(down, up)) } >>> down return down(up(a).map(hylo(down, up)))
} }
/// Reiteration through `Syntax`. /// 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`. /// 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. /// `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 { public func hylo<A, B, Leaf, Annotation>(down: (Annotation, Syntax<B, Leaf>) -> B, _ up: A -> (Annotation, Syntax<A, Leaf>))(_ a: A) -> B {
return up >>> { ($0, $1.map(hylo(down, up))) } >>> down let (annotation, syntax) = up(a)
return down(annotation, syntax.map(hylo(down, up)))
} }
@ -89,12 +90,12 @@ extension Syntax {
switch (left, right) { switch (left, right) {
case let (.Leaf(l1), .Leaf(l2)): case let (.Leaf(l1), .Leaf(l2)):
return leaf(l1, l2) return leaf(l1, l2)
case let (.Indexed(v1), .Indexed(v2)): case let (.Indexed(v1), .Indexed(v2)) where v1.count == v2.count:
return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 } return zip(v1, v2).reduce(true) { $0 && recur($1) }
case let (.Fixed(v1), .Fixed(v2)): case let (.Fixed(v1), .Fixed(v2)) where v1.count == v2.count:
return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 } return zip(v1, v2).reduce(true) { $0 && recur($1) }
case let (.Keyed(d1), .Keyed(d2)): case let (.Keyed(d1), .Keyed(d2)) where Set(d1.keys) == Set(d2.keys):
return Set(d1.keys) == Set(d2.keys) && d1.keys.map { recur(d1[$0]!, d2[$0]!) }.reduce(true) { $0 && $1 } return d1.keys.reduce(true) { $0 && recur(d1[$1]!, d2[$1]!) }
default: default:
return false return false
} }

View File

@ -14,15 +14,15 @@ extension TermType {
/// Catamorphism over `TermType`s. /// 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. /// 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 { public func cata<Result>(transform: Syntax<Result, Leaf> throws -> Result) rethrows -> Result {
return self |> (Self.unwrap >>> { $0.map { $0.cata(transform) } } >>> transform) return try transform(unwrap.map { try $0.cata(transform) })
} }
/// Paramorphism over `TermType`s. /// 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. /// 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 { public func para<Result>(transform: Syntax<(Self, Result), Leaf> throws -> Result) rethrows -> Result {
return self |> (Self.unwrap >>> { $0.map { ($0, $0.para(transform)) } } >>> transform) return try transform(unwrap.map { try ($0, $0.para(transform)) })
} }

55
prototype/UI/diff.js vendored
View File

@ -67,10 +67,12 @@ function wrap(tagName, element) {
} }
/// String -> Syntax a -> Range -> (a -> Range) -> (a -> DOM) -> DOM /// 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) { 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; var element;
if (syntax.leaf != null) { if (syntax.leaf != null) {
element = document.createElement("span"); element = document.createElement("span");
@ -83,18 +85,9 @@ function rangeAndSyntaxToDOM(source, syntax, range, getRange, recur) {
var child = values[i]; var child = values[i];
if (child.pure == "") continue; if (child.pure == "") continue;
var childRange = getRange(child); var childRange = getRange(child);
if (childRange.before != null) { element.appendChild(document.createTextNode(source.substr(previous, childRange[0] - previous)));
var beforeRange = childRange.before; element.appendChild(wrap("li", recur(child)));
element.appendChild(document.createTextNode(source.substr(previous, beforeRange[0] - previous))); previous = childRange[0] + childRange[1];
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, range[0] + range[1] - previous))); element.appendChild(document.createTextNode(source.substr(previous, range[0] + range[1] - previous)));
} else if (syntax.keyed != null) { } 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.appendChild(document.createTextNode(source.substr(previous, range[0] + range[1] - previous)));
} }
element["data-range"] = range; element["data-range"] = range;
for (index in categories) {
element.classList.add('category-'+categories[index]);
}
return element; return element;
} }
@ -137,11 +135,11 @@ function diffToDOM(diff, sources) {
if (diffOrTerm.pure != null) { if (diffOrTerm.pure != null) {
var beforeRange, afterRange; var beforeRange, afterRange;
if (diffOrTerm.pure.before != null) { if (diffOrTerm.pure.before != null) {
beforeRange = diffOrTerm.pure.before.extract beforeRange = diffOrTerm.pure.before.extract.range
} }
if (diffOrTerm.pure.after != null) { if (diffOrTerm.pure.after != null) {
afterRange = diffOrTerm.pure.after.extract afterRange = diffOrTerm.pure.after.extract.range
} }
if (beforeRange == null) { if (beforeRange == null) {
@ -154,10 +152,10 @@ function diffToDOM(diff, sources) {
return { "before": beforeRange, "after": afterRange }; return { "before": beforeRange, "after": afterRange };
} }
if (diffOrTerm.roll != null) { 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) { 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) { function pureToDOM(sources, patch, getRangeFun, diffToDOMFun) {
var elementA, elementB; var elementA, elementB;
if (patch.before != null) { 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"); elementA.classList.add("delete");
if (patch.after != null) { if (patch.after != null) {
elementA.classList.add("replace"); elementA.classList.add("replace");
@ -183,7 +181,7 @@ function pureToDOM(sources, patch, getRangeFun, diffToDOMFun) {
} }
if (patch.after != null) { 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"); elementB.classList.add("insert");
if (patch.before != null) { if (patch.before != null) {
elementB.classList.add("replace"); elementB.classList.add("replace");
@ -205,7 +203,14 @@ function pureToDOM(sources, patch, getRangeFun, diffToDOMFun) {
function rollToDOM(sources, rollOrTerm, getRangeFun, diffToDOMFun) { function rollToDOM(sources, rollOrTerm, getRangeFun, diffToDOMFun) {
var syntax = rollOrTerm.unwrap 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 elementA;
var elementB; var elementB;
@ -429,6 +434,14 @@ function rollToDOM(sources, rollOrTerm, getRangeFun, diffToDOMFun) {
elementB.appendChild(document.createTextNode(textB)); 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 } return { "before": elementA, "after": elementB }
} }

0
prototype/UI/dom.js vendored
View File

View File

@ -29,25 +29,69 @@
background-color: #ffffec; background-color: #ffffec;
outline: 1px solid #e9e9c0; outline: 1px solid #e9e9c0;
} }
.invisible {
background-color: #fff; .invisible {
visibility: hidden; background-color: #fff;
} visibility: hidden;
}
.diff div, .diff ul, .diff li, .diff dl, .diff dd, .diff span { .diff div, .diff ul, .diff li, .diff dl, .diff dd, .diff span {
white-space: pre-wrap; white-space: pre-wrap;
display: inline; display: inline;
margin: 0; margin: 0;
padding: 0; padding: 0;
color: initial;
} }
.diff dt { .diff dt {
display: none; 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> </style>
<script type="text/javascript" src="dictionary.js"></script> <script type="text/javascript" src="dictionary.js"></script>
<script type="text/javascript" src="diff.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="patch.js"></script>
<script type="text/javascript" src="syntax.js"></script> <script type="text/javascript" src="syntax.js"></script>
<script type="text/javascript" src="term.js"></script> <script type="text/javascript" src="term.js"></script>
@ -66,16 +110,15 @@
</script> </script>
</head> </head>
<body> <body>
<div id="before" class="diff"></div> <div id="before" class="diff"></div>
<div id="after" class="diff"></div> <div id="after" class="diff"></div>
<script type="text/javascript"> <script type="text/javascript">
loadJSON((window.location.search || '?diff.json').substr(1), function (json) { loadJSON((window.location.search || '?diff.json').substr(1), function (json) {
var diff = diffFromJSON(json.diff); var diff = diffFromJSON(json.diff);
var dom = diffToDOM(diff, { "before": json["before"] , "after": json["after"] })
var dom = diffToDOM(diff, { "before": json["before"] , "after": json["after"] }) document.getElementById("before").appendChild(dom.before);
document.getElementById("before").appendChild(dom.before); document.getElementById("after").appendChild(dom.after);
document.getElementById("after").appendChild(dom.after);
}); });
</script> </script>
</body> </body>

View File

@ -12,12 +12,3 @@ function Term(object) {
this.unwrap = object.unwrap; this.unwrap = object.unwrap;
return this; 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);
});
}

View File

@ -26,20 +26,20 @@ extension TSNode {
var namedChildren: ChildrenCollection { var namedChildren: ChildrenCollection {
return ChildrenCollection(node: self, count: ts_node_named_child_count(self), child: ts_node_named_child) return ChildrenCollection(node: self, count: ts_node_named_child_count(self), child: ts_node_named_child)
} }
}
struct ChildrenCollection: CollectionType { struct ChildrenCollection: CollectionType {
let node: TSNode let node: TSNode
let count: Int let count: Int
let child: (TSNode, Int) -> TSNode let child: (TSNode, Int) -> TSNode
subscript (index: Int) -> TSNode { subscript (index: Int) -> TSNode {
return child(node, index) return child(node, index)
} }
let startIndex = 0 let startIndex = 0
var endIndex: Int { var endIndex: Int {
return count return count
}
} }
} }

View File

@ -3,9 +3,9 @@ import Doubt
import Prelude import Prelude
import Madness 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 start = NSDate.timeIntervalSinceReferenceDate()
let result = f() let result = try f()
let end = NSDate.timeIntervalSinceReferenceDate() let end = NSDate.timeIntervalSinceReferenceDate()
print((label.map { "\($0): " } ?? "") + "\(end - start)s") print((label.map { "\($0): " } ?? "") + "\(end - start)s")
return result 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 arguments: Argument = try parsed.either(ifLeft: { throw "\($0)" }, ifRight: { $0 })
let (aSource, bSource) = arguments.sources let (aSource, bSource) = arguments.sources
let jsonURL = NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).URLByAppendingPathComponent("diff.json") 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 "cant compare files of different types" } guard aSource.type == bSource.type else { throw "cant compare files of different types" }
let parser = parserForType(aSource.type) let parser = parserForType(aSource.type)
let a = try parser(aSource.contents) let a = try benchmark("parsing source a") { try parser(aSource.contents) }
let b = try parser(bSource.contents) let b = try benchmark("parsing source 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 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 { switch arguments.output {
case .Split: case .Split:
let JSON: Doubt.JSON = [ let JSON: Doubt.JSON = [
"before": .String(aSource.contents), "before": .String(aSource.contents),
"after": .String(bSource.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, "before": $0.JSON,
"after": $1.range.JSON, "after": $1.JSON,
] ]
}), }),
] ]
@ -178,5 +178,5 @@ case .Split:
NSWorkspace.sharedWorkspace().openURL(URL) NSWorkspace.sharedWorkspace().openURL(URL)
} }
case .Unified: 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) })
} }