package json import ( "fmt" "strings" ) type navigation struct { root node } // Implementation of hcled.ContextString func (n navigation) ContextString(offset int) string { steps := navigationStepsRev(n.root, offset) if steps == nil { return "" } // We built our slice backwards, so we'll reverse it in-place now. half := len(steps) / 2 // integer division for i := 0; i < half; i++ { steps[i], steps[len(steps)-1-i] = steps[len(steps)-1-i], steps[i] } ret := strings.Join(steps, "") if len(ret) > 0 && ret[0] == '.' { ret = ret[1:] } return ret } func navigationStepsRev(v node, offset int) []string { switch tv := v.(type) { case *objectVal: // Do any of our properties have an object that contains the target // offset? for _, attr := range tv.Attrs { k := attr.Name av := attr.Value switch av.(type) { case *objectVal, *arrayVal: // okay default: continue } if av.Range().ContainsOffset(offset) { return append(navigationStepsRev(av, offset), "."+k) } } case *arrayVal: // Do any of our elements contain the target offset? for i, elem := range tv.Values { switch elem.(type) { case *objectVal, *arrayVal: // okay default: continue } if elem.Range().ContainsOffset(offset) { return append(navigationStepsRev(elem, offset), fmt.Sprintf("[%d]", i)) } } } return nil }