diff --git a/.golangci.yaml b/.golangci.yaml index c2c8b52b..c9c9f620 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -24,7 +24,6 @@ linters: - nosprintfhostport - staticcheck - tenv - - testifylint - unconvert - unused - usestdlibvars diff --git a/readline/buffer.go b/readline/buffer.go index 68573d40..d91fe0a9 100644 --- a/readline/buffer.go +++ b/readline/buffer.go @@ -62,7 +62,7 @@ func (b *Buffer) MoveLeft() { rLength := runewidth.RuneWidth(r) if b.DisplayPos%b.LineWidth == 0 { - fmt.Printf(CursorUp + CursorBOL + cursorRightN(b.Width)) + fmt.Print(CursorUp + CursorBOL + CursorRightN(b.Width)) if rLength == 2 { fmt.Print(CursorLeft) } @@ -74,7 +74,7 @@ func (b *Buffer) MoveLeft() { fmt.Print(CursorLeft) } } else { - fmt.Print(cursorLeftN(rLength)) + fmt.Print(CursorLeftN(rLength)) } b.Pos -= 1 @@ -115,15 +115,15 @@ func (b *Buffer) MoveRight() { b.DisplayPos += rLength if b.DisplayPos%b.LineWidth == 0 { - fmt.Printf(CursorDown + CursorBOL + cursorRightN(len(b.Prompt.prompt()))) + fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt()))) } else if (b.DisplayPos-rLength)%b.LineWidth == b.LineWidth-1 && hasSpace { - fmt.Printf(CursorDown + CursorBOL + cursorRightN(len(b.Prompt.prompt())+rLength)) + fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt())+rLength)) b.DisplayPos += 1 } else if b.LineHasSpace.Size() > 0 && b.DisplayPos%b.LineWidth == b.LineWidth-1 && hasSpace { - fmt.Printf(CursorDown + CursorBOL + cursorRightN(len(b.Prompt.prompt()))) + fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt()))) b.DisplayPos += 1 } else { - fmt.Print(cursorRightN(rLength)) + fmt.Print(CursorRightN(rLength)) } } } @@ -154,7 +154,7 @@ func (b *Buffer) MoveToStart() { fmt.Print(CursorUp) } } - fmt.Printf(CursorBOL + cursorRightN(len(b.Prompt.prompt()))) + fmt.Print(CursorBOL + CursorRightN(len(b.Prompt.prompt()))) b.Pos = 0 b.DisplayPos = 0 } @@ -169,9 +169,9 @@ func (b *Buffer) MoveToEnd() { fmt.Print(CursorDown) } remainder := b.DisplaySize() % b.LineWidth - fmt.Printf(CursorBOL + cursorRightN(len(b.Prompt.prompt())+remainder)) + fmt.Print(CursorBOL + CursorRightN(len(b.Prompt.prompt())+remainder)) } else { - fmt.Print(cursorRightN(b.DisplaySize() - b.DisplayPos)) + fmt.Print(CursorRightN(b.DisplaySize() - b.DisplayPos)) } b.Pos = b.Buf.Size() @@ -286,8 +286,7 @@ func (b *Buffer) drawRemaining() { remLength := runewidth.StringWidth(remainingText) if len(currLine) > 0 { - fmt.Printf(ClearToEOL + currLine) - fmt.Print(cursorLeftN(currLineSpace)) + fmt.Print(ClearToEOL + currLine + CursorLeftN(currLineSpace)) } else { fmt.Print(ClearToEOL) } @@ -301,9 +300,9 @@ func (b *Buffer) drawRemaining() { } if (b.DisplayPos+currLineSpace)%b.LineWidth == 0 && currLine == remainingText { - fmt.Print(cursorRightN(currLineSpace)) + fmt.Print(CursorRightN(currLineSpace)) fmt.Printf("\n%s", b.Prompt.AltPrompt) - fmt.Printf(CursorUp + CursorBOL + cursorRightN(b.Width-currLineSpace)) + fmt.Print(CursorUp + CursorBOL + CursorRightN(b.Width-currLineSpace)) } // render the other lines @@ -333,9 +332,7 @@ func (b *Buffer) drawRemaining() { lineLength += runewidth.RuneWidth(c) fmt.Printf("%c", c) } - fmt.Print(ClearToEOL) - fmt.Print(cursorUpN(totalLines)) - fmt.Printf(CursorBOL + cursorRightN(b.Width-currLineSpace)) + fmt.Print(ClearToEOL + CursorUpN(totalLines) + CursorBOL + CursorRightN(b.Width-currLineSpace)) hasSpace := b.GetLineSpacing(b.DisplayPos / b.LineWidth) @@ -357,8 +354,7 @@ func (b *Buffer) Remove() { if b.DisplayPos%b.LineWidth == 0 { // if the user backspaces over the word boundary, do this magic to clear the line // and move to the end of the previous line - fmt.Printf(CursorBOL + ClearToEOL) - fmt.Printf(CursorUp + CursorBOL + cursorRightN(b.Width)) + fmt.Print(CursorBOL + ClearToEOL + CursorUp + CursorBOL + CursorRightN(b.Width)) if b.DisplaySize()%b.LineWidth < (b.DisplaySize()-rLength)%b.LineWidth { b.LineHasSpace.Remove(b.DisplayPos/b.LineWidth - 1) @@ -370,24 +366,23 @@ func (b *Buffer) Remove() { } if rLength == 2 { - fmt.Print(CursorLeft + " " + cursorLeftN(2)) + fmt.Print(CursorLeft + " " + CursorLeftN(2)) } else { fmt.Print(" " + CursorLeft) } } else if (b.DisplayPos-rLength)%b.LineWidth == 0 && hasSpace { - fmt.Printf(CursorBOL + ClearToEOL) - fmt.Printf(CursorUp + CursorBOL + cursorRightN(b.Width)) + fmt.Print(CursorBOL + ClearToEOL + CursorUp + CursorBOL + CursorRightN(b.Width)) if b.Pos == b.Buf.Size() { b.LineHasSpace.Remove(b.DisplayPos/b.LineWidth - 1) } b.DisplayPos -= 1 } else { - fmt.Print(cursorLeftN(rLength)) + fmt.Print(CursorLeftN(rLength)) for range rLength { fmt.Print(" ") } - fmt.Print(cursorLeftN(rLength)) + fmt.Print(CursorLeftN(rLength)) } var eraseExtraLine bool @@ -405,9 +400,9 @@ func (b *Buffer) Remove() { // are trailing characters which go over the line width boundary if eraseExtraLine { remainingLines := (b.DisplaySize() - b.DisplayPos) / b.LineWidth - fmt.Printf(cursorDownN(remainingLines+1) + CursorBOL + ClearToEOL) + fmt.Print(CursorDownN(remainingLines+1) + CursorBOL + ClearToEOL) place := b.DisplayPos % b.LineWidth - fmt.Printf(cursorUpN(remainingLines+1) + cursorRightN(place+len(b.Prompt.prompt()))) + fmt.Print(CursorUpN(remainingLines+1) + CursorRightN(place+len(b.Prompt.prompt()))) } } } @@ -422,9 +417,9 @@ func (b *Buffer) Delete() { if b.DisplaySize()%b.LineWidth == 0 { if b.DisplayPos != b.DisplaySize() { remainingLines := (b.DisplaySize() - b.DisplayPos) / b.LineWidth - fmt.Printf(cursorDownN(remainingLines) + CursorBOL + ClearToEOL) + fmt.Print(CursorDownN(remainingLines) + CursorBOL + ClearToEOL) place := b.DisplayPos % b.LineWidth - fmt.Printf(cursorUpN(remainingLines) + cursorRightN(place+len(b.Prompt.prompt()))) + fmt.Print(CursorUpN(remainingLines) + CursorRightN(place+len(b.Prompt.prompt()))) } } } @@ -471,17 +466,17 @@ func (b *Buffer) DeleteWord() { } func (b *Buffer) ClearScreen() { - fmt.Printf(ClearScreen + CursorReset + b.Prompt.prompt()) + fmt.Print(ClearScreen + CursorReset + b.Prompt.prompt()) if b.IsEmpty() { ph := b.Prompt.placeholder() - fmt.Printf(ColorGrey + ph + cursorLeftN(len(ph)) + ColorDefault) + fmt.Print(ColorGrey + ph + CursorLeftN(len(ph)) + ColorDefault) } else { currPos := b.DisplayPos currIndex := b.Pos b.Pos = 0 b.DisplayPos = 0 b.drawRemaining() - fmt.Printf(CursorReset + cursorRightN(len(b.Prompt.prompt()))) + fmt.Print(CursorReset + CursorRightN(len(b.Prompt.prompt()))) if currPos > 0 { targetLine := currPos / b.LineWidth if targetLine > 0 { @@ -491,10 +486,10 @@ func (b *Buffer) ClearScreen() { } remainder := currPos % b.LineWidth if remainder > 0 { - fmt.Print(cursorRightN(remainder)) + fmt.Print(CursorRightN(remainder)) } if currPos%b.LineWidth == 0 { - fmt.Printf(CursorBOL + b.Prompt.AltPrompt) + fmt.Print(CursorBOL + b.Prompt.AltPrompt) } } b.Pos = currIndex @@ -513,13 +508,13 @@ func (b *Buffer) Replace(r []rune) { b.Buf.Clear() - fmt.Printf(CursorBOL + ClearToEOL) + fmt.Print(CursorBOL + ClearToEOL) for range lineNums { fmt.Print(CursorUp + CursorBOL + ClearToEOL) } - fmt.Printf(CursorBOL + b.Prompt.prompt()) + fmt.Print(CursorBOL + b.Prompt.prompt()) for _, c := range r { b.Add(c) @@ -545,19 +540,3 @@ func (b *Buffer) StringNM(n, m int) string { } return s } - -func cursorLeftN(n int) string { - return fmt.Sprintf(CursorLeftN, n) -} - -func cursorRightN(n int) string { - return fmt.Sprintf(CursorRightN, n) -} - -func cursorUpN(n int) string { - return fmt.Sprintf(CursorUpN, n) -} - -func cursorDownN(n int) string { - return fmt.Sprintf(CursorDownN, n) -} diff --git a/readline/readline.go b/readline/readline.go index e90a5e01..1c14fe10 100644 --- a/readline/readline.go +++ b/readline/readline.go @@ -98,7 +98,7 @@ func (i *Instance) Readline() (string, error) { showPlaceholder := !i.Pasting || i.Prompt.UseAlt if buf.IsEmpty() && showPlaceholder { ph := i.Prompt.placeholder() - fmt.Printf(ColorGrey + ph + fmt.Sprintf(CursorLeftN, len(ph)) + ColorDefault) + fmt.Print(ColorGrey + ph + CursorLeftN(len(ph)) + ColorDefault) } r, err := i.Terminal.Read() diff --git a/readline/types.go b/readline/types.go index 3b88588f..e136d996 100644 --- a/readline/types.go +++ b/readline/types.go @@ -1,5 +1,7 @@ package readline +import "strconv" + const ( CharNull = 0 CharLineStart = 1 @@ -41,34 +43,49 @@ const ( ) const ( - CursorUp = "\033[1A" - CursorDown = "\033[1B" - CursorRight = "\033[1C" - CursorLeft = "\033[1D" + Esc = "\x1b" - CursorSave = "\033[s" - CursorRestore = "\033[u" + CursorSave = Esc + "[s" + CursorRestore = Esc + "[u" - CursorUpN = "\033[%dA" - CursorDownN = "\033[%dB" - CursorRightN = "\033[%dC" - CursorLeftN = "\033[%dD" + CursorEOL = Esc + "[E" + CursorBOL = Esc + "[1G" + CursorHide = Esc + "[?25l" + CursorShow = Esc + "[?25h" - CursorEOL = "\033[E" - CursorBOL = "\033[1G" - CursorHide = "\033[?25l" - CursorShow = "\033[?25h" + ClearToEOL = Esc + "[K" + ClearLine = Esc + "[2K" + ClearScreen = Esc + "[2J" + CursorReset = Esc + "[0;0f" - ClearToEOL = "\033[K" - ClearLine = "\033[2K" - ClearScreen = "\033[2J" - CursorReset = "\033[0;0f" + ColorGrey = Esc + "[38;5;245m" + ColorDefault = Esc + "[0m" - ColorGrey = "\033[38;5;245m" - ColorDefault = "\033[0m" + StartBracketedPaste = Esc + "[?2004h" + EndBracketedPaste = Esc + "[?2004l" +) - StartBracketedPaste = "\033[?2004h" - EndBracketedPaste = "\033[?2004l" +func CursorUpN(n int) string { + return Esc + "[" + strconv.Itoa(n) + "A" +} + +func CursorDownN(n int) string { + return Esc + "[" + strconv.Itoa(n) + "B" +} + +func CursorRightN(n int) string { + return Esc + "[" + strconv.Itoa(n) + "C" +} + +func CursorLeftN(n int) string { + return Esc + "[" + strconv.Itoa(n) + "D" +} + +var ( + CursorUp = CursorUpN(1) + CursorDown = CursorDownN(1) + CursorRight = CursorRightN(1) + CursorLeft = CursorLeftN(1) ) const ( diff --git a/server/sched.go b/server/sched.go index c378865b..9947fd32 100644 --- a/server/sched.go +++ b/server/sched.go @@ -418,7 +418,7 @@ func (s *Scheduler) load(req *LlmRequest, ggml *llm.GGML, gpus gpu.GpuInfoList, // some older models are not compatible with newer versions of llama.cpp // show a generalized compatibility error until there is a better way to // check for model compatibility - if errors.Is(llm.ErrUnsupportedFormat, err) || strings.Contains(err.Error(), "failed to load model") { + if errors.Is(err, llm.ErrUnsupportedFormat) || strings.Contains(err.Error(), "failed to load model") { err = fmt.Errorf("%v: this model may be incompatible with your version of Ollama. If you previously pulled this model, try updating it by running `ollama pull %s`", err, req.model.ShortName) } slog.Info("NewLlamaServer failed", "model", req.model.ModelPath, "error", err)