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  }