From 4cfa79158ff63fd566a2586fdfdc8dbd616c433a Mon Sep 17 00:00:00 2001 From: reugn Date: Wed, 11 Sep 2024 22:10:15 +0300 Subject: [PATCH] remove old package files --- cli/chat.go | 119 ------------------------------------- cli/color/color.go | 55 ----------------- cli/command.go | 143 --------------------------------------------- cli/prompt.go | 68 --------------------- cli/spinner.go | 69 ---------------------- 5 files changed, 454 deletions(-) delete mode 100644 cli/chat.go delete mode 100644 cli/color/color.go delete mode 100644 cli/command.go delete mode 100644 cli/prompt.go delete mode 100644 cli/spinner.go diff --git a/cli/chat.go b/cli/chat.go deleted file mode 100644 index b637c76..0000000 --- a/cli/chat.go +++ /dev/null @@ -1,119 +0,0 @@ -package cli - -import ( - "errors" - "fmt" - "strings" - - "github.com/chzyer/readline" - "github.com/reugn/gemini-cli/gemini" -) - -// ChatOpts represents Chat configuration options. -type ChatOpts struct { - Format bool - Style string - Multiline bool - Terminator string -} - -// Chat controls the chat flow. -type Chat struct { - model *gemini.ChatSession - prompt *prompt - reader *readline.Instance - opts *ChatOpts -} - -// NewChat returns a new Chat. -func NewChat(user string, model *gemini.ChatSession, opts *ChatOpts) (*Chat, error) { - reader, err := readline.NewEx(&readline.Config{}) - if err != nil { - return nil, err - } - prompt := newPrompt(user) - reader.SetPrompt(prompt.user) - if opts.Multiline { - reader.HistoryDisable() - } - return &Chat{ - model: model, - prompt: prompt, - reader: reader, - opts: opts, - }, nil -} - -// StartChat starts the chat loop. -func (c *Chat) StartChat() { - for { - message, ok := c.read() - if !ok { - continue - } - command := c.parseCommand(message) - if quit := command.run(message); quit { - break - } - } -} - -func (c *Chat) read() (string, bool) { - if c.opts.Multiline { - return c.readMultiLine() - } - return c.readLine() -} - -func (c *Chat) readLine() (string, bool) { - input, err := c.reader.Readline() - if err != nil { - return c.handleReadError(len(input), err) - } - return validateInput(input) -} - -func (c *Chat) readMultiLine() (string, bool) { - var builder strings.Builder - term := c.opts.Terminator - for { - input, err := c.reader.Readline() - if err != nil { - c.reader.SetPrompt(c.prompt.user) - return c.handleReadError(builder.Len()+len(input), err) - } - if strings.HasSuffix(input, term) { - builder.WriteString(strings.TrimSuffix(input, term)) - break - } - if builder.Len() == 0 { - c.reader.SetPrompt(c.prompt.userNext) - } - builder.WriteString(input + "\n") - } - c.reader.SetPrompt(c.prompt.user) - return validateInput(builder.String()) -} - -func (c *Chat) parseCommand(message string) command { - if strings.HasPrefix(message, systemCmdPrefix) { - return newSystemCommand(c) - } - return newGeminiCommand(c) -} - -func (c *Chat) handleReadError(inputLen int, err error) (string, bool) { - if errors.Is(err, readline.ErrInterrupt) { - if inputLen == 0 { - return systemCmdQuit, true - } - return "", false - } - fmt.Printf("%s%s\n", c.prompt.cli, err) - return "", false -} - -func validateInput(input string) (string, bool) { - input = strings.TrimSpace(input) - return input, input != "" -} diff --git a/cli/color/color.go b/cli/color/color.go deleted file mode 100644 index 9f462ab..0000000 --- a/cli/color/color.go +++ /dev/null @@ -1,55 +0,0 @@ -package color - -import "fmt" - -const ( - reset = "\033[0m" - red = "\033[31m" - green = "\033[32m" - yellow = "\033[33m" - blue = "\033[34m" - magenta = "\033[35m" - cyan = "\033[36m" - gray = "\033[37m" - white = "\033[97m" -) - -// Red adds red color to str in terminal. -func Red(str string) string { - return fmt.Sprintf("%s%s%s", red, str, reset) -} - -// Green adds green color to str in terminal. -func Green(str string) string { - return fmt.Sprintf("%s%s%s", green, str, reset) -} - -// Yellow adds yellow color to str in terminal. -func Yellow(str string) string { - return fmt.Sprintf("%s%s%s", yellow, str, reset) -} - -// Blue adds blue color to str in terminal. -func Blue(str string) string { - return fmt.Sprintf("%s%s%s", blue, str, reset) -} - -// Magenta adds magenta color to str in terminal. -func Magenta(str string) string { - return fmt.Sprintf("%s%s%s", magenta, str, reset) -} - -// Cyan adds cyan color to str in terminal. -func Cyan(str string) string { - return fmt.Sprintf("%s%s%s", cyan, str, reset) -} - -// Gray adds gray color to str in terminal. -func Gray(str string) string { - return fmt.Sprintf("%s%s%s", gray, str, reset) -} - -// White adds white color to str in terminal. -func White(str string) string { - return fmt.Sprintf("%s%s%s", white, str, reset) -} diff --git a/cli/command.go b/cli/command.go deleted file mode 100644 index 1432a82..0000000 --- a/cli/command.go +++ /dev/null @@ -1,143 +0,0 @@ -package cli - -import ( - "bufio" - "errors" - "fmt" - "os" - "strings" - "time" - - "github.com/charmbracelet/glamour" - "github.com/reugn/gemini-cli/cli/color" - "google.golang.org/api/iterator" -) - -const ( - systemCmdPrefix = "!" - systemCmdQuit = "!q" - systemCmdPurgeHistory = "!p" - systemCmdToggleInputMode = "!m" -) - -type command interface { - run(message string) bool -} - -type systemCommand struct { - chat *Chat -} - -var _ command = (*systemCommand)(nil) - -func newSystemCommand(chat *Chat) command { - return &systemCommand{ - chat: chat, - } -} - -func (c *systemCommand) run(message string) bool { - switch message { - case systemCmdQuit: - c.print("Exiting gemini-cli...") - return true - case systemCmdPurgeHistory: - c.chat.model.ClearHistory() - c.print("Cleared the chat history.") - case systemCmdToggleInputMode: - if c.chat.opts.Multiline { - c.print("Switched to single-line input mode.") - c.chat.reader.HistoryEnable() - c.chat.opts.Multiline = false - } else { - c.print("Switched to multi-line input mode.") - // disable history for multi-line messages since it is - // unusable for future requests - c.chat.reader.HistoryDisable() - c.chat.opts.Multiline = true - } - default: - c.print("Unknown system command.") - } - return false -} - -func (c *systemCommand) print(message string) { - fmt.Printf("%s%s\n", c.chat.prompt.cli, message) -} - -type geminiCommand struct { - chat *Chat - spinner *spinner - writer *bufio.Writer -} - -var _ command = (*geminiCommand)(nil) - -func newGeminiCommand(chat *Chat) command { - writer := bufio.NewWriter(os.Stdout) - return &geminiCommand{ - chat: chat, - spinner: newSpinner(5, time.Second, writer), - writer: writer, - } -} - -func (c *geminiCommand) run(message string) bool { - c.printFlush(c.chat.prompt.gemini) - c.spinner.start() - if c.chat.opts.Format { - // requires the entire response to be formatted - c.runBlocking(message) - } else { - c.runStreaming(message) - } - return false -} - -func (c *geminiCommand) runBlocking(message string) { - response, err := c.chat.model.SendMessage(message) - c.spinner.stop() - if err != nil { - fmt.Println(color.Red(err.Error())) - } else { - var buf strings.Builder - for _, candidate := range response.Candidates { - for _, part := range candidate.Content.Parts { - buf.WriteString(fmt.Sprintf("%s", part)) - } - } - output, err := glamour.Render(buf.String(), c.chat.opts.Style) - if err != nil { - fmt.Printf(color.Red("Failed to format: %s\n"), err) - fmt.Println(buf.String()) - return - } - fmt.Print(output) - } -} - -func (c *geminiCommand) runStreaming(message string) { - responseIterator := c.chat.model.SendMessageStream(message) - c.spinner.stop() - for { - response, err := responseIterator.Next() - if err != nil { - if !errors.Is(err, iterator.Done) { - fmt.Print(color.Red(err.Error())) - } - break - } - for _, candidate := range response.Candidates { - for _, part := range candidate.Content.Parts { - c.printFlush(fmt.Sprintf("%s", part)) - } - } - } - fmt.Print("\n") -} - -func (c *geminiCommand) printFlush(message string) { - fmt.Fprintf(c.writer, "%s", message) - c.writer.Flush() -} diff --git a/cli/prompt.go b/cli/prompt.go deleted file mode 100644 index 6b3cb90..0000000 --- a/cli/prompt.go +++ /dev/null @@ -1,68 +0,0 @@ -package cli - -import ( - "fmt" - "strings" - - "github.com/muesli/termenv" - "github.com/reugn/gemini-cli/cli/color" -) - -const ( - geminiUser = "gemini" - cliUser = "cli" -) - -type prompt struct { - user string - userNext string - gemini string - cli string -} - -type promptColor struct { - user func(string) string - gemini func(string) string - cli func(string) string -} - -func newPromptColor() *promptColor { - if termenv.HasDarkBackground() { - return &promptColor{ - user: color.Cyan, - gemini: color.Green, - cli: color.Yellow, - } - } - return &promptColor{ - user: color.Blue, - gemini: color.Green, - cli: color.Magenta, - } -} - -func newPrompt(currentUser string) *prompt { - maxLength := maxLength(currentUser, geminiUser, cliUser) - pc := newPromptColor() - return &prompt{ - user: pc.user(buildPrompt(currentUser, maxLength)), - userNext: pc.user(buildPrompt(strings.Repeat(" ", len(currentUser)), maxLength)), - gemini: pc.gemini(buildPrompt(geminiUser, maxLength)), - cli: pc.cli(buildPrompt(cliUser, maxLength)), - } -} - -func maxLength(str ...string) int { - var maxLength int - for _, s := range str { - length := len(s) - if maxLength < length { - maxLength = length - } - } - return maxLength -} - -func buildPrompt(user string, length int) string { - return fmt.Sprintf("%s>%s", user, strings.Repeat(" ", length-len(user)+1)) -} diff --git a/cli/spinner.go b/cli/spinner.go deleted file mode 100644 index da72766..0000000 --- a/cli/spinner.go +++ /dev/null @@ -1,69 +0,0 @@ -package cli - -import ( - "bufio" - "fmt" - "time" -) - -const ( - moveCursorBackward = "\033[%dD" - clearLineFromCursor = "\033[K" - progressRune = '.' -) - -type spinner struct { - length int - interval time.Duration - writer *bufio.Writer - signal chan struct{} -} - -func newSpinner(length int, interval time.Duration, writer *bufio.Writer) *spinner { - return &spinner{ - length: length, - interval: interval, - writer: writer, - signal: make(chan struct{}), - } -} - -//nolint:errcheck -func (s *spinner) start() { - go func() { - ticker := time.NewTicker(s.interval) - defer ticker.Stop() - var n int - for { - select { - case <-s.signal: - if n > 0 { - s.clear(n) - } - s.signal <- struct{}{} - return - case <-ticker.C: - if n < s.length { - s.writer.WriteRune(progressRune) - s.writer.Flush() - n++ - } else { - s.clear(n) - n = 0 - } - } - } - }() -} - -//nolint:errcheck -func (s *spinner) clear(n int) { - s.writer.WriteString(fmt.Sprintf(moveCursorBackward, n)) - s.writer.WriteString(clearLineFromCursor) - s.writer.Flush() -} - -func (s *spinner) stop() { - s.signal <- struct{}{} - <-s.signal -}