github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/expressions/globbing.go (about)

     1  package expressions
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"strings"
     7  	"sync"
     8  
     9  	"github.com/lmorg/murex/utils/ansi/codes"
    10  	"github.com/lmorg/murex/utils/escape"
    11  	"github.com/lmorg/murex/utils/readline"
    12  )
    13  
    14  func (tree *ParserT) parseGlob(glob []rune) ([]string, error) {
    15  	globS := string(glob)
    16  
    17  	match, globErr := filepath.Glob(globS)
    18  	expand, err := expandGlobPrompt(tree.statement.String(), globS, match)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  	if !expand {
    23  		return nil, nil
    24  	}
    25  
    26  	if globErr != nil {
    27  		return nil, fmt.Errorf("invalid glob: '%s'\n%s", globS, err.Error())
    28  	}
    29  	if len(match) == 0 {
    30  		return nil, fmt.Errorf("glob returned zero results.\nglob: '%s'", globS)
    31  	}
    32  
    33  	return match, nil
    34  }
    35  
    36  var rlMutex sync.Mutex
    37  
    38  func expandGlobPrompt(cmd string, before string, match []string) (bool, error) {
    39  	rlMutex.Lock()
    40  	defer rlMutex.Unlock() // performance doesn't matter here
    41  
    42  	rl := readline.NewInstance()
    43  	prompt := fmt.Sprintf("(%s) Do you wish to expand '%s'? [yN]: ", cmd, before)
    44  	rl.SetPrompt(prompt)
    45  	rl.HintText = func(_ []rune, _ int) []rune { return autoGlobPromptHintText(rl, match) }
    46  	rl.History = new(readline.NullHistory)
    47  
    48  	for {
    49  		line, err := rl.Readline()
    50  		if err != nil {
    51  			return false, err
    52  		}
    53  
    54  		switch strings.ToLower(line) {
    55  		case "y", "yes":
    56  			return true, nil
    57  		case "", "n", "no":
    58  			return false, nil
    59  		}
    60  	}
    61  }
    62  
    63  const (
    64  	warningNoGlobMatch = "Warning: no files match that pattern"
    65  	globExpandsTo      = "Glob expands to: "
    66  )
    67  
    68  func autoGlobPromptHintText(rl *readline.Instance, match []string) []rune {
    69  	if len(match) == 0 {
    70  		rl.HintFormatting = codes.FgRed
    71  		return []rune(warningNoGlobMatch)
    72  	}
    73  
    74  	slice := make([]string, len(match))
    75  	copy(slice, match)
    76  	escape.CommandLine(slice)
    77  	after := globExpandsTo + strings.Join(slice, ", ")
    78  	return []rune(after)
    79  }