blob: 8991bdcf685b4e98fd155ca337f8a18b64d5f395 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
to diff :file1 :file2 :output
local "caseignoredp
make "caseignoredp "false
openread :file1
openread :file2
if not emptyp :output [openwrite :output]
setwrite :output
print [DIFF results:]
print sentence [< File 1 =] :file1
print sentence [> File 2 =] :file2
diff.same (makefile 1 :file1) (makefile 2 :file2)
print "==========
setread []
setwrite []
close :file1
close :file2
if not emptyp :output [close :output]
end
;; Skip over identical lines in the two files.
to diff.same :fib1 :fib2
local [line1 line2]
do.while [make "line1 getline :fib1
make "line2 getline :fib2
if and listp :line1 listp :line2 [stop] ; Both files ended.
] [equalp :line1 :line2]
addline :fib1 :line1 ; Difference found.
addline :fib2 :line2
diff.differ :fib1 :fib2
end
;; Remember differing lines while looking for ones that match.
to diff.differ :fib1 :fib2
local "line
make "line readline :fib1
addline :fib1 :line
ifelse memberp :line lines :fib2 ~
[diff.found :fib1 :fib2] ~
[diff.differ :fib2 :fib1]
end
to diff.found :fib1 :fib2
local "lines
make "lines member2 (last butlast lines :fib1) ~
(last lines :fib1) ~
(lines :fib2)
ifelse emptyp :lines ~
[diff.differ :fib2 :fib1] ~
[report :fib1 :fib2 (butlast butlast lines :fib1)
(firstn (lines :fib2) (count lines :fib2)-(count :lines))]
end
to member2 :line1 :line2 :lines
if emptyp butfirst :lines [output []]
if and equalp :line1 first :lines equalp :line2 first butfirst :lines ~
[output :lines]
output member2 :line1 :line2 butfirst :lines
end
to firstn :stuff :number
if :number = 0 [output []]
output fput (first :stuff) (firstn butfirst :stuff :number-1)
end
;; Read from file or from saved lines.
to getline :fib
nextlinenum :fib
output readline :fib
end
to readline :fib
if savedp :fib [output popsaved :fib]
setread filename :fib
output readword
end
;; Matching lines found, now report the differences.
to report :fib1 :fib2 :lines1 :lines2
local [end1 end2 dashes]
if equalp (which :fib1) 2 [report :fib2 :fib1 :lines2 :lines1 stop]
print "==========
make "end1 (linenum :fib1)+(count :lines1)-1
make "end2 (linenum :fib2)+(count :lines2)-1
make "dashes "false
ifelse :end1 < (linenum :fib1) [
print (sentence "INSERT :end1+1 (word (linenum :fib2) "- :end2))
] [ifelse :end2 < (linenum :fib2) [
print (sentence "DELETE (word (linenum :fib1) "- :end1) :end2+1)
] [
print (sentence "CHANGE (word (linenum :fib1) "- :end1)
(word (linenum :fib2) "- :end2))
make "dashes "true
]]
process :fib1 "|< | :lines1 :end1
if :dashes [print "-----]
process :fib2 "|> | :lines2 :end2
diff.same :fib1 :fib2
end
to process :fib :prompt :lines :end
foreach :lines [type :prompt print ?]
savelines :fib butfirst butfirst chop :lines (lines :fib)
setlines :fib []
setlinenum :fib :end+2
end
to chop :counter :stuff
if emptyp :counter [output :stuff]
output chop butfirst :counter butfirst :stuff
end
;; Constructor, selectors, and mutators for File Information Block (FIB)
;; Five elements: file number, file name, line number,
;; differing lines, and saved lines for re-reading.
to makefile :number :name
local "file
make "file array 5 ; Items 4 and 5 will be empty lists.
setitem 1 :file :number
setitem 2 :file :name
setitem 3 :file 0
output :file
end
to which :fib
output item 1 :fib
end
to filename :fib
output item 2 :fib
end
to linenum :fib
output item 3 :fib
end
to nextlinenum :fib
setitem 3 :fib (item 3 :fib)+1
end
to setlinenum :fib :value
setitem 3 :fib :value
end
to addline :fib :line
setitem 4 :fib (lput :line item 4 :fib)
end
to setlines :fib :value
setitem 4 :fib :value
end
to lines :fib
output item 4 :fib
end
to savelines :fib :value
setitem 5 :fib (sentence :value item 5 :fib)
end
to savedp :fib
output not emptyp item 5 :fib
end
to popsaved :fib
local "result
make "result first item 5 :fib
setitem 5 :fib (butfirst item 5 :fib)
output :result
end
|