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 }