package completion

import (
	
	
	
	

	
	
)

// Display prints the current completion list to the screen,
// respecting the current display and completion settings.
func ( *Engine,  int) {
	.usedY = 0

	defer fmt.Print(term.ClearScreenBelow)

	// The completion engine might be inactive but still having
	// a non-empty list of completions. This is on purpose, as
	// sometimes it's better to keep completions printed for a
	// little more time. The engine itself is responsible for
	// deleting those lists when it deems them useless.
	if .Matches() == 0 || .skipDisplay {
		fmt.Print(term.ClearLineAfter)
		return
	}

	// The final completions string to print.
	 := term.ClearLineAfter

	for ,  := range .groups {
		 += .renderCompletions()
	}

	// Crop the completions so that it fits within our terminal
	, .usedY = .cropCompletions(, )

	if  != "" {
		fmt.Print()
	}
}

// Coordinates returns the number of terminal rows used
// when displaying the completions with Display().
func ( *Engine) int {
	return .usedY
}

// renderCompletions renders all completions in a given list (with aliases or not).
// The descriptions list argument is optional.
func ( *Engine) ( *group) string {
	var  strings.Builder

	if len(.rows) == 0 {
		return ""
	}

	if .tag != "" {
		 := fmt.Sprintf("%s%s%s %s", color.Bold, color.FgYellow, .tag, color.Reset)
		.WriteString( + term.ClearLineAfter + term.NewlineReturn)
	}

	for ,  := range .rows {
		for  := range .columnsWidth {
			var  Candidate

			// If there are aliases, we might have no completions at the current
			// coordinates, so just print the corresponding padding and return.
			if len() >  {
				 = []
			}

			// Apply all highlightings to the displayed value:
			// selection, prefixes, styles and other things,
			 := .getPad(, , false)
			 :=  == .posY &&  == .posX && .isCurrent
			 := .highlightDisplay(, , , , )

			.WriteString()

			// Add description if no aliases, or if done with them.
			 :=  == len(.columnsWidth)-1
			if .aliased &&  && .Description == "" {
				 = [0]
			}

			if !.aliased ||  {
				.maxDescAllowed = .setMaximumSizes()

				 := .getPad(, , true)
				 := .highlightDesc(, , , , , )
				.WriteString()
			}
		}

		// We're done for this line.
		.WriteString(term.ClearLineAfter + term.NewlineReturn)
	}

	return .String()
}

func ( *Engine) ( *group,  Candidate, ,  int,  bool) ( string) {
	// An empty display value means padding.
	if .Display == "" {
		return padSpace()
	}

	 := color.Fmt(.Style)
	,  := .trimDisplay(, , )

	if .IsearchRegex != nil && .isearchBuf.Len() > 0 && ! {
		 := .IsearchRegex.FindString()
		 = color.Fmt(color.Bg+"244") +  + color.Reset + 
		 = .IsearchRegex.ReplaceAllLiteralString(, )
	}

	if  {
		// If the comp is currently selected, overwrite any highlighting already applied.
		 := color.UnquoteRC(.config.GetString("completion-selection-style"))
		 := color.Fmt(color.Bg+"255") + 
		 =  + 

		if .aliased {
			 += color.Reset
		}
	} else {
		// Highlight the prefix if any and configured for it.
		if .config.GetBool("colored-completion-prefix") && .prefix != "" {
			if ,  := regexp.Compile("^" + .prefix);  == nil {
				 := color.Bold + color.FgBlue + .prefix + color.BoldReset + color.FgDefault + 
				 = .ReplaceAllString(, )
			}
		}

		 =  +  + color.Reset
	}

	return  + 
}

func ( *Engine) ( *group,  Candidate, , ,  int,  bool) ( string) {
	if .Description == "" {
		return color.Reset
	}

	,  := .trimDesc(, )

	// If the next row has the same completions, replace the description with our hint.
	if len(.rows) > +1 && .rows[+1][0].Description == .Description {
		 = "|"
	} else if .IsearchRegex != nil && .isearchBuf.Len() > 0 && ! {
		 := .IsearchRegex.FindString()
		 = color.Fmt(color.Bg+"244") +  + color.Reset + color.Dim
		 = .IsearchRegex.ReplaceAllLiteralString(, )
	}

	// If the comp is currently selected, overwrite any highlighting already applied.
	// Replace all background reset escape sequences in it, to ensure correct display.
	if  == .posY &&  == .posX && .isCurrent && !.aliased {
		 := color.UnquoteRC(.config.GetString("completion-selection-style"))
		 := color.Fmt(color.Bg+"255") + 
		 = strings.ReplaceAll(, color.BgDefault, )
		 =  + 
	}

	 := color.UnquoteRC(.config.GetString("completion-description-style"))

	return  +  + color.Reset + 
}

// cropCompletions - When the user cycles through a completion list longer
// than the console MaxTabCompleterRows value, we crop the completions string
// so that "global" cycling (across all groups) is printed correctly.
func ( *Engine) ( string,  int) ( string,  int) {
	// Get the current absolute candidate position
	 := .getAbsPos()

	// Scan the completions for cutting them at newlines
	 := bufio.NewScanner(strings.NewReader())

	// If absPos < MaxTabCompleterRows, cut below MaxTabCompleterRows and return
	if  < -1 {
		return .cutCompletionsBelow(, )
	}

	// If absolute > MaxTabCompleterRows, cut above and below and return
	//      -> This includes de facto when we tabCompletionReverse
	if  >= -1 {
		return .cutCompletionsAboveBelow(, , )
	}

	return
}

func ( *Engine) ( *bufio.Scanner,  int) (string, int) {
	var  int
	var  string

	for .Scan() {
		 := .Text()
		if  < -1 {
			 +=  + term.NewlineReturn
			++
		} else {
			break
		}
	}

	 = strings.TrimSuffix(, term.NewlineReturn)

	// Add hint for remaining completions, if any.
	,  := .completionCount()
	 :=  - 

	if  <= 0 {
		return ,  - 1
	}

	 += fmt.Sprintf(term.NewlineReturn+color.Dim+color.FgYellow+" %d more completion rows... (scroll down to show)"+color.Reset, )

	return , 
}

func ( *Engine) ( *bufio.Scanner, ,  int) (string, int) {
	 :=  -  + 1

	var  string
	var  int

	for .Scan() {
		 := .Text()

		if  <=  {
			++

			continue
		}

		if  >  &&  <=  {
			 +=  + term.NewlineReturn
			++
		} else {
			break
		}
	}

	 = strings.TrimSuffix(, term.NewlineReturn)
	 -=  + 1

	// Add hint for remaining completions, if any.
	,  := .completionCount()
	 :=  - ( + )

	if  <= 0 {
		return ,  - 1
	}

	 += fmt.Sprintf(term.NewlineReturn+color.Dim+color.FgYellow+" %d more completion rows... (scroll down to show)"+color.Reset, )

	return , 
}