github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/edit/nodeutil.go (about) 1 package edit 2 3 import ( 4 "strings" 5 6 "github.com/elves/elvish/parse" 7 "github.com/elves/elvish/util" 8 ) 9 10 // Utilities for insepcting the AST. Used for completers and stylists. 11 12 func isFormHead(compound *parse.Compound) bool { 13 if form, ok := compound.Parent().(*parse.Form); ok { 14 return form.Head == compound 15 } 16 return false 17 } 18 19 func formHead(n parse.Node) (parse.Node, string) { 20 if _, ok := n.(*parse.Chunk); ok { 21 return n, "" 22 } 23 24 if primary, ok := n.(*parse.Primary); ok { 25 if compound, head := primaryInSimpleCompound(primary); compound != nil { 26 if form, ok := compound.Parent().(*parse.Form); ok { 27 if form.Head == compound { 28 return compound, head 29 } 30 } 31 } 32 } 33 34 return nil, "" 35 } 36 37 func primaryInSimpleCompound(pn *parse.Primary) (*parse.Compound, string) { 38 thisIndexing, ok := pn.Parent().(*parse.Indexing) 39 if !ok { 40 return nil, "" 41 } 42 thisCompound, ok := thisIndexing.Parent().(*parse.Compound) 43 if !ok { 44 return nil, "" 45 } 46 ok, head := simpleCompound(thisCompound, thisIndexing) 47 if !ok { 48 return nil, "" 49 } 50 return thisCompound, head 51 } 52 53 func simpleCompound(cn *parse.Compound, upto *parse.Indexing) (bool, string) { 54 tilde := false 55 head := "" 56 for _, in := range cn.Indexings { 57 if len(in.Indicies) > 0 { 58 return false, "" 59 } 60 switch in.Head.Type { 61 case parse.Tilde: 62 tilde = true 63 case parse.Bareword, parse.SingleQuoted, parse.DoubleQuoted: 64 head += in.Head.Value 65 } 66 67 if in == upto { 68 break 69 } 70 } 71 if tilde { 72 i := strings.Index(head, "/") 73 if i == -1 { 74 return false, "" 75 } 76 uname := head[:i] 77 home, err := util.GetHome(uname) 78 if err != nil { 79 // TODO report error 80 return false, "" 81 } 82 head = home + head[i:] 83 } 84 return true, head 85 }