github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/readline/tabmap.go (about)

     1  package readline
     2  
     3  import "fmt"
     4  
     5  func (rl *Instance) initTabMap() {
     6  	rl.tabMutex.Lock()
     7  	defer rl.tabMutex.Unlock()
     8  
     9  	var suggestions *suggestionsT
    10  	if rl.modeTabFind {
    11  		suggestions = newSuggestionsT(rl, rl.tfSuggestions)
    12  	} else {
    13  		suggestions = newSuggestionsT(rl, rl.tcSuggestions)
    14  	}
    15  
    16  	rl.tcMaxLength = 1
    17  	//for i := range suggestions {
    18  	for i := 0; i < suggestions.Len(); i++ {
    19  		if rl.tcDisplayType == TabDisplayList {
    20  			if suggestions.ItemLen(i) > rl.tcMaxLength {
    21  				rl.tcMaxLength = suggestions.ItemLen(i)
    22  			}
    23  
    24  		} else {
    25  			if len(rl.tcDescriptions[suggestions.ItemLookupValue(i)]) > rl.tcMaxLength {
    26  				rl.tcMaxLength = len(rl.tcDescriptions[suggestions.ItemLookupValue(i)])
    27  			}
    28  		}
    29  	}
    30  
    31  	rl.tcPosX = 1
    32  	rl.tcPosY = 1
    33  	rl.tcOffset = 0
    34  	rl.tcMaxX = 1
    35  
    36  	if suggestions.Len() > rl.MaxTabCompleterRows {
    37  		rl.tcMaxY = rl.MaxTabCompleterRows
    38  	} else {
    39  		rl.tcMaxY = suggestions.Len()
    40  	}
    41  }
    42  
    43  func (rl *Instance) moveTabMapHighlight(x, y int) {
    44  	rl.tabMutex.Lock()
    45  	defer rl.tabMutex.Unlock()
    46  
    47  	var suggestions *suggestionsT
    48  	if rl.modeTabFind {
    49  		suggestions = newSuggestionsT(rl, rl.tfSuggestions)
    50  	} else {
    51  		suggestions = newSuggestionsT(rl, rl.tcSuggestions)
    52  	}
    53  
    54  	rl.tcPosY += x
    55  	rl.tcPosY += y
    56  
    57  	if rl.tcPosY < 1 {
    58  		rl.tcPosY = 1
    59  		rl.tcOffset--
    60  	}
    61  
    62  	if rl.tcPosY > rl.tcMaxY {
    63  		rl.tcPosY--
    64  		rl.tcOffset++
    65  	}
    66  
    67  	if rl.tcOffset+rl.tcPosY < 1 && suggestions.Len() > 0 {
    68  		rl.tcPosY = rl.tcMaxY
    69  		rl.tcOffset = suggestions.Len() - rl.tcMaxY
    70  	}
    71  
    72  	if rl.tcOffset < 0 {
    73  		rl.tcOffset = 0
    74  	}
    75  
    76  	if rl.tcOffset+rl.tcPosY > suggestions.Len() {
    77  		rl.tcPosY = 1
    78  		rl.tcOffset = 0
    79  	}
    80  }
    81  
    82  func (rl *Instance) writeTabMapStr() string {
    83  	rl.tabMutex.Lock()
    84  	defer rl.tabMutex.Unlock()
    85  
    86  	var suggestions *suggestionsT
    87  	if rl.modeTabFind {
    88  		suggestions = newSuggestionsT(rl, rl.tfSuggestions)
    89  	} else {
    90  		suggestions = newSuggestionsT(rl, rl.tcSuggestions)
    91  	}
    92  
    93  	if rl.termWidth < 10 {
    94  		// terminal too small. Probably better we do nothing instead of crash
    95  		return ""
    96  	}
    97  
    98  	maxLength := rl.tcMaxLength
    99  	if maxLength > rl.termWidth-9 {
   100  		maxLength = rl.termWidth - 9
   101  	}
   102  	maxDescWidth := rl.termWidth - maxLength - 4
   103  
   104  	y := 0
   105  	rl.previewItem = ""
   106  
   107  	// bit of a kludge. Really should find where the code is "\n"ing
   108  	output := moveCursorUpStr(1)
   109  
   110  	isTabDisplayList := rl.tcDisplayType == TabDisplayList
   111  
   112  	var item, description string
   113  	for i := rl.tcOffset; i < suggestions.Len(); i++ {
   114  		y++
   115  		if y > rl.tcMaxY {
   116  			break
   117  		}
   118  
   119  		if isTabDisplayList {
   120  			item = runeWidthTruncate(suggestions.ItemValue(i), maxLength)
   121  			description = runeWidthTruncate(rl.tcDescriptions[suggestions.ItemLookupValue(i)], maxDescWidth)
   122  
   123  		} else {
   124  			item = runeWidthTruncate(suggestions.ItemValue(i), maxDescWidth)
   125  			description = runeWidthTruncate(rl.tcDescriptions[suggestions.ItemLookupValue(i)], maxLength)
   126  		}
   127  
   128  		if isTabDisplayList {
   129  			output += fmt.Sprintf("\r\n%s %s %s %s",
   130  				highlight(rl, y), runeWidthFillRight(item, maxLength),
   131  				seqReset, description)
   132  
   133  		} else {
   134  			output += fmt.Sprintf("\r\n %s %s %s %s",
   135  				runeWidthFillRight(description, maxLength), highlight(rl, y),
   136  				runeWidthFillRight(item, maxDescWidth), seqReset)
   137  
   138  		}
   139  
   140  		if y == rl.tcPosY {
   141  			rl.previewItem = suggestions.ItemValue(i)
   142  		}
   143  	}
   144  
   145  	if suggestions.Len() < rl.tcMaxX {
   146  		rl.tcUsedY = suggestions.Len()
   147  	} else {
   148  		rl.tcUsedY = rl.tcMaxY
   149  	}
   150  
   151  	return output
   152  }
   153  
   154  func highlight(rl *Instance, y int) string {
   155  	if y == rl.tcPosY {
   156  		return seqBgWhite + seqFgBlack
   157  	}
   158  	return ""
   159  }