Fix issues with inputting and formatting multi line strings in ollama run

Co-authored-by: Wen Sun <iwendellsun@gmail.com>
This commit is contained in:
Jeffrey Morgan 2023-11-25 23:30:34 -05:00
parent 82b9b329ff
commit 9fb5e8399c
3 changed files with 36 additions and 38 deletions

View file

@ -602,14 +602,12 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "")
} }
prompt := readline.Prompt{ scanner, err := readline.New(readline.Prompt{
Prompt: ">>> ", Prompt: ">>> ",
AltPrompt: "... ", AltPrompt: "... ",
Placeholder: "Send a message (/? for help)", Placeholder: "Send a message (/? for help)",
AltPlaceholder: `Use """ to end multi-line input`, AltPlaceholder: `Use """ to end multi-line input`,
} })
scanner, err := readline.New(prompt)
if err != nil { if err != nil {
return err return err
} }
@ -617,7 +615,7 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
fmt.Print(readline.StartBracketedPaste) fmt.Print(readline.StartBracketedPaste)
defer fmt.Printf(readline.EndBracketedPaste) defer fmt.Printf(readline.EndBracketedPaste)
var multiLineBuffer string var prompt string
for { for {
line, err := scanner.Readline() line, err := scanner.Readline()
@ -630,27 +628,33 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
fmt.Println("\nUse Ctrl-D or /bye to exit.") fmt.Println("\nUse Ctrl-D or /bye to exit.")
} }
scanner.Prompt.UseAlt = false
prompt = ""
continue continue
case err != nil: case err != nil:
return err return err
} }
line = strings.TrimSpace(line)
switch { switch {
case scanner.Prompt.UseAlt: case strings.HasPrefix(prompt, `"""`):
if strings.HasSuffix(line, `"""`) { // if the prompt so far starts with """ then we're in multiline mode
scanner.Prompt.UseAlt = false // and we need to keep reading until we find a line that ends with """
multiLineBuffer += strings.TrimSuffix(line, `"""`) cut, found := strings.CutSuffix(line, `"""`)
line = multiLineBuffer prompt += cut + "\n"
multiLineBuffer = ""
} else { if !found {
multiLineBuffer += line + " "
continue continue
} }
case strings.HasPrefix(line, `"""`):
prompt = strings.TrimPrefix(prompt, `"""`)
scanner.Prompt.UseAlt = false
case strings.HasPrefix(line, `"""`) && len(prompt) == 0:
scanner.Prompt.UseAlt = true scanner.Prompt.UseAlt = true
multiLineBuffer = strings.TrimPrefix(line, `"""`) + " " prompt += line + "\n"
continue
case scanner.Pasting:
prompt += line + "\n"
continue continue
case strings.HasPrefix(line, "/list"): case strings.HasPrefix(line, "/list"):
args := strings.Fields(line) args := strings.Fields(line)
@ -757,12 +761,17 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
case strings.HasPrefix(line, "/"): case strings.HasPrefix(line, "/"):
args := strings.Fields(line) args := strings.Fields(line)
fmt.Printf("Unknown command '%s'. Type /? for help\n", args[0]) fmt.Printf("Unknown command '%s'. Type /? for help\n", args[0])
continue
default:
prompt += line
} }
if len(line) > 0 && line[0] != '/' { if len(prompt) > 0 && prompt[0] != '/' {
if err := generate(cmd, model, line, wordWrap, format); err != nil { if err := generate(cmd, model, prompt, wordWrap, format); err != nil {
return err return err
} }
prompt = ""
} }
} }
} }

View file

@ -24,6 +24,7 @@ type Instance struct {
Prompt *Prompt Prompt *Prompt
Terminal *Terminal Terminal *Terminal
History *History History *History
Pasting bool
} }
func New(prompt Prompt) (*Instance, error) { func New(prompt Prompt) (*Instance, error) {
@ -46,7 +47,7 @@ func New(prompt Prompt) (*Instance, error) {
func (i *Instance) Readline() (string, error) { func (i *Instance) Readline() (string, error) {
prompt := i.Prompt.Prompt prompt := i.Prompt.Prompt
if i.Prompt.UseAlt { if i.Prompt.UseAlt || i.Pasting {
prompt = i.Prompt.AltPrompt prompt = i.Prompt.AltPrompt
} }
fmt.Print(prompt) fmt.Print(prompt)
@ -63,12 +64,13 @@ func (i *Instance) Readline() (string, error) {
var esc bool var esc bool
var escex bool var escex bool
var metaDel bool var metaDel bool
var pasteMode PasteMode
var currentLineBuf []rune var currentLineBuf []rune
for { for {
if buf.IsEmpty() { // don't show placeholder when pasting unless we're in multiline mode
showPlaceholder := !i.Pasting || i.Prompt.UseAlt
if buf.IsEmpty() && showPlaceholder {
ph := i.Prompt.Placeholder ph := i.Prompt.Placeholder
if i.Prompt.UseAlt { if i.Prompt.UseAlt {
ph = i.Prompt.AltPlaceholder ph = i.Prompt.AltPlaceholder
@ -119,9 +121,9 @@ func (i *Instance) Readline() (string, error) {
code += string(r) code += string(r)
} }
if code == CharBracketedPasteStart { if code == CharBracketedPasteStart {
pasteMode = PasteModeStart i.Pasting = true
} else if code == CharBracketedPasteEnd { } else if code == CharBracketedPasteEnd {
pasteMode = PasteModeEnd i.Pasting = false
} }
case KeyDel: case KeyDel:
if buf.Size() > 0 { if buf.Size() > 0 {
@ -196,12 +198,7 @@ func (i *Instance) Readline() (string, error) {
} }
buf.MoveToEnd() buf.MoveToEnd()
fmt.Println() fmt.Println()
switch pasteMode {
case PasteModeStart:
output = `"""` + output
case PasteModeEnd:
output = output + `"""`
}
return output, nil return output, nil
default: default:
if metaDel { if metaDel {

View file

@ -76,11 +76,3 @@ const (
CharBracketedPasteStart = "00~" CharBracketedPasteStart = "00~"
CharBracketedPasteEnd = "01~" CharBracketedPasteEnd = "01~"
) )
type PasteMode int
const (
PastModeOff = iota
PasteModeStart
PasteModeEnd
)