108 lines
2 KiB
Ruby
108 lines
2 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module IpynbDiff
|
||
|
require 'oj'
|
||
|
|
||
|
# Creates a map from a symbol to the line number it appears in a Json file
|
||
|
#
|
||
|
# Example:
|
||
|
#
|
||
|
# Input:
|
||
|
#
|
||
|
# 1. {
|
||
|
# 2. 'obj1': [
|
||
|
# 3. {
|
||
|
# 4. 'obj2': 5
|
||
|
# 5. },
|
||
|
# 6. 3,
|
||
|
# 7. {
|
||
|
# 8. 'obj3': {
|
||
|
# 9. 'obj4': 'b'
|
||
|
# 10. }
|
||
|
# 11. }
|
||
|
# 12. ]
|
||
|
# 13.}
|
||
|
#
|
||
|
# Output:
|
||
|
#
|
||
|
# Symbol Line Number
|
||
|
# .obj1 -> 2
|
||
|
# .obj1.0 -> 3
|
||
|
# .obj1.0 -> 3
|
||
|
# .obj1.0.obj2 -> 4
|
||
|
# .obj1.1 -> 6
|
||
|
# .obj1.2 -> 7
|
||
|
# .obj1.2.obj3 -> 8
|
||
|
# .obj1.2.obj3.obj4 -> 9
|
||
|
#
|
||
|
class SymbolMap
|
||
|
class << self
|
||
|
def handler
|
||
|
@handler ||= SymbolMap.new
|
||
|
end
|
||
|
|
||
|
def parser
|
||
|
@parser ||= Oj::Parser.new(:saj).tap { |p| p.handler = handler }
|
||
|
end
|
||
|
|
||
|
def parse(notebook, *args)
|
||
|
handler.reset
|
||
|
parser.parse(notebook)
|
||
|
handler.symbols
|
||
|
end
|
||
|
end
|
||
|
|
||
|
attr_accessor :symbols
|
||
|
|
||
|
def hash_start(key, line, column)
|
||
|
add_symbol(key_or_index(key), line)
|
||
|
end
|
||
|
|
||
|
def hash_end(key, line, column)
|
||
|
@current_path.pop
|
||
|
end
|
||
|
|
||
|
def array_start(key, line, column)
|
||
|
@current_array_index << 0
|
||
|
|
||
|
add_symbol(key, line)
|
||
|
end
|
||
|
|
||
|
def array_end(key, line, column)
|
||
|
@current_path.pop
|
||
|
@current_array_index.pop
|
||
|
end
|
||
|
|
||
|
def add_value(value, key, line, column)
|
||
|
add_symbol(key_or_index(key), line)
|
||
|
|
||
|
@current_path.pop
|
||
|
end
|
||
|
|
||
|
def add_symbol(symbol, line)
|
||
|
@symbols[@current_path.append(symbol).join('.')] = line if symbol
|
||
|
end
|
||
|
|
||
|
def key_or_index(key)
|
||
|
if key.nil? # value in an array
|
||
|
if @current_path.empty?
|
||
|
@current_path = ['']
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
symbol = @current_array_index.last
|
||
|
@current_array_index[-1] += 1
|
||
|
symbol
|
||
|
else
|
||
|
key
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def reset
|
||
|
@current_path = []
|
||
|
@symbols = {}
|
||
|
@current_array_index = []
|
||
|
end
|
||
|
end
|
||
|
end
|