package carapace
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/carapace-sh/carapace/internal/env"
"github.com/carapace-sh/carapace/internal/shell/zsh"
"github.com/carapace-sh/carapace/pkg/execlog"
"github.com/carapace-sh/carapace/pkg/util"
"github.com/carapace-sh/carapace/third_party/github.com/drone/envsubst"
"github.com/spf13/cobra"
)
type Context struct {
Value string
Args []string
Parts []string
Env []string
Dir string
mockedReplies map [string ]string
cmd *cobra .Command
}
func NewContext (args ...string ) Context {
if len (args ) == 0 {
args = append (args , "" )
}
context := Context {
Value : args [len (args )-1 ],
Args : args [:len (args )-1 ],
Env : os .Environ (),
}
if wd , err := os .Getwd (); err == nil {
context .Dir = wd
}
if m , err := env .Sandbox (); err == nil {
context .Dir = m .WorkDir ()
context .mockedReplies = m .Replies
}
return context
}
func (c Context ) LookupEnv (key string ) (string , bool ) {
prefix := key + "="
for i := len (c .Env ) - 1 ; i >= 0 ; i -- {
if env := c .Env [i ]; strings .HasPrefix (env , prefix ) {
return strings .SplitN (env , "=" , 2 )[1 ], true
}
}
return "" , false
}
func (c Context ) Getenv (key string ) string {
v , _ := c .LookupEnv (key )
return v
}
func (c *Context ) Setenv (key , value string ) {
if c .Env == nil {
c .Env = []string {}
}
c .Env = append (c .Env , fmt .Sprintf ("%v=%v" , key , value ))
}
func (c Context ) Envsubst (s string ) (string , error ) {
return envsubst .Eval (s , c .Getenv )
}
func (c Context ) Command (name string , arg ...string ) *execlog .Cmd {
if c .mockedReplies != nil {
if m , err := json .Marshal (append ([]string {name }, arg ...)); err == nil {
if reply , exists := c .mockedReplies [string (m )]; exists {
return execlog .Command ("echo" , reply )
}
}
}
cmd := execlog .Command (name , arg ...)
cmd .Env = c .Env
cmd .Dir = c .Dir
return cmd
}
func expandHome(s string ) (string , error ) {
if strings .HasPrefix (s , "~" ) {
if zsh .NamedDirectories .Matches (s ) {
return zsh .NamedDirectories .Replace (s ), nil
}
home , err := os .UserHomeDir ()
if err != nil {
return "" , err
}
home = filepath .ToSlash (home )
switch s {
case "~" :
s = home
default :
s = strings .Replace (s , "~/" , home +"/" , 1 )
}
}
return s , nil
}
func (c Context ) Abs (path string ) (string , error ) {
path = filepath .ToSlash (path )
if !strings .HasPrefix (path , "/" ) && !strings .HasPrefix (path , "~" ) && !util .HasVolumePrefix (path ) {
switch c .Dir {
case "" :
path = "./" + path
default :
path = c .Dir + "/" + path
}
}
path , err := expandHome (path )
if err != nil {
return "" , err
}
if len (path ) == 2 && util .HasVolumePrefix (path ) {
path += "/"
}
result , err := filepath .Abs (path )
if err != nil {
return "" , err
}
result = filepath .ToSlash (result )
if strings .HasSuffix (path , "/" ) && !strings .HasSuffix (result , "/" ) {
result += "/"
} else if strings .HasSuffix (path , "/." ) && !strings .HasSuffix (result , "/." ) {
result += "/."
}
return result , nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .