github.com/alecthomas/kong@v0.9.1-0.20240410131203-2ab5733f1179/visit.go (about) 1 package kong 2 3 import ( 4 "fmt" 5 ) 6 7 // Next should be called by Visitor to proceed with the walk. 8 // 9 // The walk will terminate if "err" is non-nil. 10 type Next func(err error) error 11 12 // Visitor can be used to walk all nodes in the model. 13 type Visitor func(node Visitable, next Next) error 14 15 // Visit all nodes. 16 func Visit(node Visitable, visitor Visitor) error { 17 return visitor(node, func(err error) error { 18 if err != nil { 19 return err 20 } 21 switch node := node.(type) { 22 case *Application: 23 return visitNodeChildren(node.Node, visitor) 24 case *Node: 25 return visitNodeChildren(node, visitor) 26 case *Value: 27 case *Flag: 28 return Visit(node.Value, visitor) 29 default: 30 panic(fmt.Sprintf("unsupported node type %T", node)) 31 } 32 return nil 33 }) 34 } 35 36 func visitNodeChildren(node *Node, visitor Visitor) error { 37 if node.Argument != nil { 38 if err := Visit(node.Argument, visitor); err != nil { 39 return err 40 } 41 } 42 for _, flag := range node.Flags { 43 if err := Visit(flag, visitor); err != nil { 44 return err 45 } 46 } 47 for _, pos := range node.Positional { 48 if err := Visit(pos, visitor); err != nil { 49 return err 50 } 51 } 52 for _, child := range node.Children { 53 if err := Visit(child, visitor); err != nil { 54 return err 55 } 56 } 57 return nil 58 }