From e648ed50a412d3ca44564909bb2184c439b06bfe Mon Sep 17 00:00:00 2001 From: Moby von Briesen Date: Sat, 22 Apr 2023 21:56:52 -0400 Subject: [PATCH] Add ability to copy LLM prompt directly to clipboard --- cmd/root.go | 27 +++++++++++++++++++++------ go.mod | 1 + go.sum | 2 ++ pullpal/common.go | 17 +++++++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 17d1546..c144312 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,6 +4,7 @@ import ( "fmt" "os" + "github.com/mobyvb/pull-pal/llm" "github.com/mobyvb/pull-pal/pullpal" "github.com/mobyvb/pull-pal/vc" "github.com/spf13/cobra" @@ -32,6 +33,7 @@ It can be used to: githubToken := viper.GetString("github-token") localRepoPath := viper.GetString("local-repo-path") promptPath := viper.GetString("prompt-path") + promptToClipboard := viper.GetBool("prompt-to-clipboard") responsePath := viper.GetString("response-path") log, err := zap.NewProduction() @@ -59,13 +61,24 @@ It can be used to: } log.Info("Successfully initialized pull pal") - issue, changeRequest, err := p.PickIssueToFile(promptPath) - if err != nil { - log.Error("error selecting issue and/or generating prompt", zap.Error(err)) - return - } + var issue vc.Issue + var changeRequest llm.CodeChangeRequest + if promptToClipboard { + issue, changeRequest, err = p.PickIssueToClipboard(promptPath) + if err != nil { + log.Error("error selecting issue and/or generating prompt", zap.Error(err)) + return + } - log.Info("Picked issue and created prompt", zap.String("issue ID", issue.ID), zap.String("prompt location", promptPath)) + log.Info("Picked issue and copied prompt to clipboard", zap.String("issue ID", issue.ID)) + } else { + issue, changeRequest, err = p.PickIssueToFile(promptPath) + if err != nil { + log.Error("error selecting issue and/or generating prompt", zap.Error(err)) + return + } + log.Info("Picked issue and created prompt", zap.String("issue ID", issue.ID), zap.String("prompt location", promptPath)) + } log.Info("Insert LLM response into response file", zap.String("response location", responsePath)) @@ -107,6 +120,7 @@ func init() { rootCmd.PersistentFlags().StringP("repo-name", "n", "REPO-NAME", "name of repository on version control server") rootCmd.PersistentFlags().StringP("github-token", "t", "GITHUB TOKEN", "token for authenticating Github actions") rootCmd.PersistentFlags().StringP("local-repo-path", "l", "/tmp/pullpalrepo/", "path where pull pal will check out a local copy of the repository") + rootCmd.PersistentFlags().BoolP("prompt-to-clipboard", "c", false, "whether to copy LLM prompt to clipboard rather than using a file") rootCmd.PersistentFlags().StringP("prompt-path", "p", "./path/to/prompt.txt", "path where pull pal will write the llm prompt") rootCmd.PersistentFlags().StringP("response-path", "r", "./path/to/response.txt", "path where pull pal will read the llm response from") @@ -117,6 +131,7 @@ func init() { viper.BindPFlag("repo-name", rootCmd.PersistentFlags().Lookup("repo-name")) viper.BindPFlag("github-token", rootCmd.PersistentFlags().Lookup("github-token")) viper.BindPFlag("local-repo-path", rootCmd.PersistentFlags().Lookup("local-repo-path")) + viper.BindPFlag("prompt-to-clipboard", rootCmd.PersistentFlags().Lookup("prompt-to-clipboard")) viper.BindPFlag("prompt-path", rootCmd.PersistentFlags().Lookup("prompt-path")) viper.BindPFlag("response-path", rootCmd.PersistentFlags().Lookup("response-path")) } diff --git a/go.mod b/go.mod index 96bd074..9ff6cdb 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/mobyvb/pull-pal go 1.20 require ( + github.com/atotto/clipboard v0.1.4 github.com/go-git/go-git/v5 v5.6.1 github.com/google/go-github v17.0.0+incompatible github.com/spf13/cobra v1.7.0 diff --git a/go.sum b/go.sum index c7744a6..a160420 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/pullpal/common.go b/pullpal/common.go index e5d8d21..ecee81e 100644 --- a/pullpal/common.go +++ b/pullpal/common.go @@ -9,6 +9,7 @@ import ( "github.com/mobyvb/pull-pal/llm" "github.com/mobyvb/pull-pal/vc" + "github.com/atotto/clipboard" "go.uber.org/zap" ) @@ -58,6 +59,22 @@ func (p *PullPal) PickIssueToFile(promptPath string) (issue vc.Issue, changeRequ return issue, changeRequest, err } +// PickIssueToClipboard is the same as PickIssue, but the changeRequest is converted to a string and copied to the clipboard. +func (p *PullPal) PickIssueToClipboard(promptPath string) (issue vc.Issue, changeRequest llm.CodeChangeRequest, err error) { + issue, changeRequest, err = p.PickIssue() + if err != nil { + return issue, changeRequest, err + } + + prompt, err := changeRequest.GetPrompt() + if err != nil { + return issue, changeRequest, err + } + + err = clipboard.WriteAll(prompt) + return issue, changeRequest, err +} + // PickIssue selects an issue from the version control server and returns the selected issue, as well as the LLM prompt needed to fulfill the request. func (p *PullPal) PickIssue() (issue vc.Issue, changeRequest llm.CodeChangeRequest, err error) { // TODO I should be able to pass in settings for listing issues from here