Skip to content

Commit 8b8a9e3

Browse files
committed
Fix log printer
1 parent e90f875 commit 8b8a9e3

File tree

1 file changed

+78
-63
lines changed

1 file changed

+78
-63
lines changed

Sources/LoggerMiddleware/LoggerMiddleware.swift

Lines changed: 78 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,31 @@ public final class LoggerMiddleware<AppAction, AppState: Equatable>: Middleware
88
public typealias StateType = AppState
99

1010
private var getState: GetState<StateType>?
11-
private let printer: (StaticString, CVarArg...) -> Void
12-
13-
public init(printer: ((StaticString, CVarArg...) -> Void)? = nil) {
14-
self.printer = printer ?? { (message: StaticString, args: CVarArg...) -> Void in os_log(.debug, log: .default, message, args) }
15-
}
16-
17-
public init(printer: @escaping (String) -> Void) {
18-
self.printer = { (message: StaticString, args: CVarArg...) -> Void in printer(String(format: "\(message)", args)) }
11+
private let actionTransform: (AppAction, ActionSource) -> String
12+
private let actionPrinter: (String) -> Void
13+
private let stateDiffTransform: (AppState, AppState) -> String?
14+
private let stateDiffPrinter: (String?) -> Void
15+
16+
public init(
17+
actionTransform: @escaping (AppAction, ActionSource) -> String = { "🕹 \(LoggerMiddleware.dumpToString($0)) from \($1)"},
18+
actionPrinter: @escaping (String) -> Void = { os_log(.debug, log: .default, "%{PUBLIC}@", $0) },
19+
stateDiffTransform: @escaping (AppState, AppState) -> String? = {
20+
let stateBefore = LoggerMiddleware.dumpToString($0)
21+
let stateAfter = LoggerMiddleware.dumpToString($1)
22+
return LoggerMiddleware.diff(old: stateBefore, new: stateAfter, linesOfContext: 2, prefixLines: "🏛 ")
23+
},
24+
stateDiffPrinter: @escaping (String?) -> Void = { state in
25+
if let state = state {
26+
os_log(.debug, log: .default, "%{PUBLIC}@", state)
27+
} else {
28+
os_log(.debug, log: .default, "%{PUBLIC}@", "🏛 No state mutation")
29+
}
30+
}
31+
) {
32+
self.actionTransform = actionTransform
33+
self.actionPrinter = actionPrinter
34+
self.stateDiffTransform = stateDiffTransform
35+
self.stateDiffPrinter = stateDiffPrinter
1936
}
2037

2138
public func receiveContext(getState: @escaping GetState<StateType>, output: AnyActionHandler<OutputActionType>) {
@@ -25,27 +42,67 @@ public final class LoggerMiddleware<AppAction, AppState: Equatable>: Middleware
2542
public func handle(action: InputActionType, from dispatcher: ActionSource, afterReducer: inout AfterReducer) {
2643
guard let getState = self.getState else { return }
2744

28-
var stateBefore = ""
29-
dump(getState(), to: &stateBefore, name: nil, indent: 2)
45+
let stateBefore = getState()
46+
let actionMessage = actionTransform(action, dispatcher)
47+
3048
afterReducer = .do {
31-
var stateAfter = ""
32-
dump(getState(), to: &stateAfter, name: nil, indent: 2)
49+
let stateAfter = getState()
50+
51+
self.actionPrinter(actionMessage)
52+
self.stateDiffPrinter(self.stateDiffTransform(stateBefore, stateAfter))
53+
}
54+
}
3355

34-
let message = "🕹 \(action) from \(dispatcher)"
35-
self.printer("%{PUBLIC}@", message)
56+
public static func dumpToString<T>(_ something: T, indent: Int = 2) -> String {
57+
var output = ""
58+
dump(something, to: &output, name: nil, indent: indent)
59+
return output
60+
}
3661

37-
if let stateString = diff(old: stateBefore, new: stateAfter) {
38-
self.printer("\n%{PUBLIC}@", stateString)
39-
} else {
40-
self.printer("🏛 No state mutation")
41-
}
62+
public static func diff(old: String, new: String, linesOfContext: Int, prefixLines: String = "") -> String? {
63+
guard old != new else { return nil }
64+
let oldSplit = old.split(separator: "\n", omittingEmptySubsequences: false).map(String.init)
65+
let newSplit = new.split(separator: "\n", omittingEmptySubsequences: false).map(String.init)
66+
67+
return chunk(
68+
diff: diff(oldSplit, newSplit),
69+
context: linesOfContext
70+
).lazy.flatMap { [$0.patchMark] + $0.lines }.map { "\(prefixLines)\($0)" }.joined(separator: "\n")
71+
}
72+
73+
public static func diff(_ fst: [String], _ snd: [String]) -> [Difference<String>] {
74+
var idxsOf = [String: [Int]]()
75+
fst.enumerated().forEach { idxsOf[$1, default: []].append($0) }
4276

43-
self.printer("")
77+
let sub = snd.enumerated().reduce((overlap: [Int: Int](), fst: 0, snd: 0, len: 0)) { sub, sndPair in
78+
(idxsOf[sndPair.element] ?? [])
79+
.reduce((overlap: [Int: Int](), fst: sub.fst, snd: sub.snd, len: sub.len)) { innerSub, fstIdx in
80+
81+
var newOverlap = innerSub.overlap
82+
newOverlap[fstIdx] = (sub.overlap[fstIdx - 1] ?? 0) + 1
83+
84+
if let newLen = newOverlap[fstIdx], newLen > sub.len {
85+
return (newOverlap, fstIdx - newLen + 1, sndPair.offset - newLen + 1, newLen)
86+
}
87+
return (newOverlap, innerSub.fst, innerSub.snd, innerSub.len)
88+
}
89+
}
90+
let (_, fstIdx, sndIdx, len) = sub
91+
92+
if len == 0 {
93+
let fstDiff = fst.isEmpty ? [] : [Difference(elements: fst, which: .first)]
94+
let sndDiff = snd.isEmpty ? [] : [Difference(elements: snd, which: .second)]
95+
return fstDiff + sndDiff
96+
} else {
97+
let fstDiff = diff(Array(fst.prefix(upTo: fstIdx)), Array(snd.prefix(upTo: sndIdx)))
98+
let midDiff = [Difference(elements: Array(fst.suffix(from: fstIdx).prefix(len)), which: .both)]
99+
let lstDiff = diff(Array(fst.suffix(from: fstIdx + len)), Array(snd.suffix(from: sndIdx + len)))
100+
return fstDiff + midDiff + lstDiff
44101
}
45102
}
46103
}
47104

48-
struct Difference<A> {
105+
public struct Difference<A> {
49106
enum Which {
50107
case first
51108
case second
@@ -56,48 +113,6 @@ struct Difference<A> {
56113
let which: Which
57114
}
58115

59-
func diff(old: String, new: String) -> String? {
60-
guard old != new else { return nil }
61-
let oldSplit = old.split(separator: "\n", omittingEmptySubsequences: false).map(String.init)
62-
let newSplit = new.split(separator: "\n", omittingEmptySubsequences: false).map(String.init)
63-
64-
return chunk(
65-
diff: diff(oldSplit, newSplit),
66-
context: 2 // Lines before and after the changes to be shown as context
67-
).lazy.flatMap { [$0.patchMark] + $0.lines }.map { "🏛 \($0)" }.joined(separator: "\n")
68-
}
69-
70-
func diff(_ fst: [String], _ snd: [String]) -> [Difference<String>] {
71-
var idxsOf = [String: [Int]]()
72-
fst.enumerated().forEach { idxsOf[$1, default: []].append($0) }
73-
74-
let sub = snd.enumerated().reduce((overlap: [Int: Int](), fst: 0, snd: 0, len: 0)) { sub, sndPair in
75-
(idxsOf[sndPair.element] ?? [])
76-
.reduce((overlap: [Int: Int](), fst: sub.fst, snd: sub.snd, len: sub.len)) { innerSub, fstIdx in
77-
78-
var newOverlap = innerSub.overlap
79-
newOverlap[fstIdx] = (sub.overlap[fstIdx - 1] ?? 0) + 1
80-
81-
if let newLen = newOverlap[fstIdx], newLen > sub.len {
82-
return (newOverlap, fstIdx - newLen + 1, sndPair.offset - newLen + 1, newLen)
83-
}
84-
return (newOverlap, innerSub.fst, innerSub.snd, innerSub.len)
85-
}
86-
}
87-
let (_, fstIdx, sndIdx, len) = sub
88-
89-
if len == 0 {
90-
let fstDiff = fst.isEmpty ? [] : [Difference(elements: fst, which: .first)]
91-
let sndDiff = snd.isEmpty ? [] : [Difference(elements: snd, which: .second)]
92-
return fstDiff + sndDiff
93-
} else {
94-
let fstDiff = diff(Array(fst.prefix(upTo: fstIdx)), Array(snd.prefix(upTo: sndIdx)))
95-
let midDiff = [Difference(elements: Array(fst.suffix(from: fstIdx).prefix(len)), which: .both)]
96-
let lstDiff = diff(Array(fst.suffix(from: fstIdx + len)), Array(snd.suffix(from: sndIdx + len)))
97-
return fstDiff + midDiff + lstDiff
98-
}
99-
}
100-
101116
let minus = ""
102117
let plus = "+"
103118
private let figureSpace = "\u{2007}"

0 commit comments

Comments
 (0)