@@ -65,7 +65,7 @@ func selectOption(title string, options []string) (int, error) {
6565 defer restore (fd , state )
6666
6767 selected := 0
68- renderMenu (title , options , selected , "" )
68+ lines := renderMenuBlock (title , options , selected , "" , true )
6969
7070 reader := bufio .NewReader (os .Stdin )
7171 for {
@@ -81,12 +81,12 @@ func selectOption(title string, options []string) (int, error) {
8181 if selected > 0 {
8282 selected --
8383 }
84- renderMenu (title , options , selected , "" )
84+ lines = updateMenu (title , options , selected , "" , lines )
8585 case 's' , 'j' :
8686 if selected < len (options )- 1 {
8787 selected ++
8888 }
89- renderMenu (title , options , selected , "" )
89+ lines = updateMenu (title , options , selected , "" , lines )
9090 case 13 , 10 :
9191 clearScreen ()
9292 return selected , nil
@@ -105,7 +105,7 @@ func selectOption(title string, options []string) (int, error) {
105105 selected ++
106106 }
107107 }
108- renderMenu (title , options , selected , "" )
108+ lines = updateMenu (title , options , selected , "" , lines )
109109 case 0 , 224 :
110110 code , err := reader .ReadByte ()
111111 if err != nil {
@@ -117,7 +117,7 @@ func selectOption(title string, options []string) (int, error) {
117117 if code == 80 && selected < len (options )- 1 {
118118 selected ++
119119 }
120- renderMenu (title , options , selected , "" )
120+ lines = updateMenu (title , options , selected , "" , lines )
121121 }
122122 }
123123}
@@ -141,22 +141,50 @@ func readEscapeSequence(reader *bufio.Reader) (string, error) {
141141 return string ([]byte {b1 , b2 }), nil
142142}
143143
144- func renderMenu (title string , options []string , selected int , hint string ) {
145- clearScreen ()
146- fmt .Println (style (title , colorAccent ))
147- fmt .Println ()
144+ func renderMenuBlock (title string , options []string , selected int , hint string , clear bool ) int {
145+ if clear {
146+ clearScreen ()
147+ }
148+ lines := 0
149+ lines += printLine (style (title , colorAccent ))
150+ lines += printLine ("" )
148151 for i , option := range options {
149152 if i == selected {
150- fmt .Printf ("%s %s\n " , style (">" , colorAccent + colorBold ), style (option , colorBold ))
153+ lines += printLine ( fmt .Sprintf ("%s %s" , style (">" , colorAccent + colorBold ), style (option , colorBold ) ))
151154 continue
152155 }
153- fmt .Printf (" %s\n " , option )
156+ lines += printLine ( fmt .Sprintf (" %s" , option ) )
154157 }
155- fmt . Println ( )
158+ lines += printLine ( "" )
156159 if hint == "" {
157160 hint = "Pfeiltasten (oder W/S), Enter zum Bestätigen"
158161 }
159- fmt .Println (style (hint , colorDim ))
162+ lines += printLine (style (hint , colorDim ))
163+ return lines
164+ }
165+
166+ func updateMenu (title string , options []string , selected int , hint string , lines int ) int {
167+ if lines > 0 {
168+ moveCursorUp (lines )
169+ }
170+ return renderMenuBlock (title , options , selected , hint , false )
171+ }
172+
173+ func printLine (value string ) int {
174+ clearLine ()
175+ fmt .Println (value )
176+ return 1
177+ }
178+
179+ func clearLine () {
180+ fmt .Print ("\r \033 [K" )
181+ }
182+
183+ func moveCursorUp (lines int ) {
184+ if lines <= 0 {
185+ return
186+ }
187+ fmt .Printf ("\033 [%dA" , lines )
160188}
161189
162190func clearScreen () {
@@ -198,17 +226,31 @@ func withSpinner(title, message string, tick time.Duration, action func() (strin
198226 }{result : result , err : err }
199227 }()
200228
229+ clearScreen ()
230+ fmt .Println (style (title , colorAccent ))
231+ fmt .Println ()
232+
201233 frames := []string {"⠋" , "⠙" , "⠹" , "⠸" , "⠼" , "⠴" , "⠦" , "⠧" , "⠇" , "⠏" }
202234 ticker := time .NewTicker (tick )
203235 defer ticker .Stop ()
204236
205237 frame := 0
238+ lastLen := 0
206239 for {
207240 select {
208241 case res := <- resultCh :
242+ if lastLen > 0 {
243+ fmt .Print ("\r " , strings .Repeat (" " , lastLen ), "\r " )
244+ }
245+ fmt .Println ()
209246 return res .result , res .err
210247 case <- ticker .C :
211- renderSpinnerPage (title , message , frames [frame ])
248+ line := fmt .Sprintf ("%s %s" , style (message , colorDim ), style (frames [frame ], colorAccent ))
249+ if lastLen > 0 && len (line ) < lastLen {
250+ line += strings .Repeat (" " , lastLen - len (line ))
251+ }
252+ fmt .Print ("\r " , line )
253+ lastLen = len (line )
212254 frame = (frame + 1 ) % len (frames )
213255 }
214256 }
0 commit comments