package edit

import (
	
	
	
	
	

	
	
	
	
	
	
	
)

//elvdoc:var prompt
//
// See [Prompts](#prompts).

//elvdoc:var -prompt-eagerness
//
// See [Prompt Eagerness](#prompt-eagerness).

//elvdoc:var prompt-stale-threshold
//
// See [Stale Prompt](#stale-prompt).

//elvdoc:var prompt-stale-transformer.
//
// See [Stale Prompt](#stale-prompt).

//elvdoc:var rprompt
//
// See [Prompts](#prompts).

//elvdoc:var -rprompt-eagerness
//
// See [Prompt Eagerness](#prompt-eagerness).

//elvdoc:var rprompt-stale-threshold
//
// See [Stale Prompt](#stale-prompt).

//elvdoc:var rprompt-stale-transformer.
//
// See [Stale Prompt](#stale-prompt).

//elvdoc:var rprompt-persistent
//
// See [RPrompt Persistency](#rprompt-persistency).

func ( *cli.AppSpec,  notifier,  *eval.Evaler,  eval.NsBuilder) {
	,  := getDefaultPromptVals()
	initPrompt(&.Prompt, "prompt", , , , )
	initPrompt(&.RPrompt, "rprompt", , , , )

	 := newBoolVar(false)
	.RPromptPersistent = func() bool { return .Get().(bool) }
	["rprompt-persistent"] = 
}

func ( *cli.Prompt,  string,  eval.Callable,  notifier,  *eval.Evaler,  eval.NsBuilder) {
	 := vars.FromPtr(&)
	[] = 
	 := newIntVar(5)
	["-"++"-eagerness"] = 
	 := newFloatVar(0.2)
	[+"-stale-threshold"] = 
	 := newFnVar(
		eval.NewGoFn("<default stale transform>", defaultStaleTransform))
	[+"-stale-transform"] = 

	* = prompt.New(prompt.Config{
		Compute: func() ui.Text {
			return callForStyledText(, , , .Get().(eval.Callable))
		},
		Eagerness: func() int { return .GetRaw().(int) },
		StaleThreshold: func() time.Duration {
			 := .GetRaw().(float64)
			return time.Duration( * float64(time.Second))
		},
		StaleTransform: func( ui.Text) ui.Text {
			return callForStyledText(, , +" stale transform", .Get().(eval.Callable), )
		},
	})
}

func () (,  eval.Callable) {
	,  := user.Current()
	 :=  == nil && .Uid == "0"

	 := "???"
	if  == nil {
		 = .Username
	}
	,  := os.Hostname()
	if  != nil {
		 = "???"
	}

	return getDefaultPrompt(), getDefaultRPrompt(, )
}

func ( bool) eval.Callable {
	 := ui.T("> ")
	if  {
		 = ui.T("# ", ui.FgRed)
	}
	return eval.NewGoFn("default prompt", func() ui.Text {
		return ui.Concat(ui.T(fsutil.Getwd()), )
	})
}

func (,  string) eval.Callable {
	 := ui.T(+"@"+, ui.Inverse)
	return eval.NewGoFn("default rprompt", func() ui.Text {
		return 
	})
}

func ( ui.Text) ui.Text {
	return ui.StyleText(, ui.Inverse)
}

// Calls a function with the given arguments and closed input, and concatenates
// its outputs to a styled text. Used to call prompts and stale transformers.
func ( notifier,  *eval.Evaler,  string,  eval.Callable,  ...interface{}) ui.Text {
	var (
		      ui.Text
		 sync.Mutex
	)
	 := func( interface{}) {
		.Lock()
		defer .Unlock()
		,  := .Concat()
		if  != nil {
			.notifyf("invalid output type from prompt: %s", vals.Kind())
		} else {
			 = .(ui.Text)
		}
	}

	// Value outputs are concatenated.
	 := func( <-chan interface{}) {
		for  := range  {
			()
		}
	}
	// Byte output is added to the prompt as a single unstyled text.
	 := func( *os.File) {
		,  := ioutil.ReadAll()
		if  != nil {
			.notifyf("error reading prompt byte output: %v", )
		}
		if len() > 0 {
			(ui.ParseSGREscapedText(string()))
		}
	}

	, ,  := eval.PipePort(, )
	if  != nil {
		.notifyf("cannot create pipe for prompt: %v", )
		return nil
	}
	,  := makeNotifyPort()

	 = .Call(,
		eval.CallCfg{Args: , From: "[" +  + "]"},
		eval.EvalCfg{Ports: []*eval.Port{nil, , }})
	()
	()

	if  != nil {
		.notifyError(, )
	}
	return 
}