170 lines
3.4 KiB
Go
170 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"github.com/abiosoft/ishell/v2"
|
|
"github.com/adrg/xdg"
|
|
"github.com/andygrunwald/go-jira"
|
|
prompt "github.com/elk-language/go-prompt"
|
|
pstrings "github.com/elk-language/go-prompt/strings"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/viper"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
var configPath string
|
|
var shell *ishell.Shell
|
|
var jiraClient *jira.Client
|
|
var promptRunner *prompt.Prompt
|
|
var prefix = "> "
|
|
|
|
func loadConfig() {
|
|
err := viper.ReadInConfig()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func SaveConfig() {
|
|
err := viper.WriteConfig()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func GetProjectId() string {
|
|
return viper.GetString("project.id")
|
|
}
|
|
|
|
func GetSprintId() int {
|
|
return viper.GetInt("sprint.id")
|
|
}
|
|
|
|
func UpdatePrompt() {
|
|
prefix = ""
|
|
if HasProject() {
|
|
prefix = prefix + "p:" + viper.GetString("project.key") + " "
|
|
}
|
|
if HasBoard() {
|
|
prefix = prefix + "b:" + viper.GetString("board.name") + " "
|
|
}
|
|
if HasSprint() {
|
|
prefix = prefix + "s:" + viper.GetString("sprint.name") + " "
|
|
}
|
|
if len(prefix) > 0 {
|
|
prefix = prefix[0:len(prefix)-1] + "> "
|
|
} else {
|
|
prefix = "> "
|
|
}
|
|
}
|
|
|
|
func executor(in string) {
|
|
command, args := GetCommand(in)
|
|
if command == nil {
|
|
println("Invalid command", in)
|
|
return
|
|
}
|
|
command.Action(args)
|
|
}
|
|
|
|
func completer(d prompt.Document) ([]prompt.Suggest, pstrings.RuneNumber, pstrings.RuneNumber) {
|
|
endIndex := d.CurrentRuneIndex()
|
|
w := d.GetWordBeforeCursor()
|
|
startIndex := endIndex - pstrings.RuneCount([]byte(w))
|
|
s := GetSuggestionsFor(d.TextBeforeCursor())
|
|
return prompt.FilterHasPrefix(s, w, true), startIndex, endIndex
|
|
}
|
|
|
|
func main() {
|
|
// Open config file
|
|
configPath, err := xdg.ConfigFile("jirashell/config.toml")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
viper.SetConfigFile(configPath)
|
|
|
|
_, err = os.Stat(configPath)
|
|
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
log.Fatal(err)
|
|
} else if err == nil {
|
|
loadConfig()
|
|
}
|
|
|
|
ensureLoggedIn()
|
|
UpdatePrompt()
|
|
|
|
promptRunner = prompt.New(
|
|
executor,
|
|
prompt.WithCompleter(completer),
|
|
prompt.WithTitle("jirashell"),
|
|
prompt.WithPrefixCallback(func() string { return prefix }),
|
|
)
|
|
promptRunner.Run()
|
|
}
|
|
|
|
func ensureLoggedIn() {
|
|
for {
|
|
username := viper.GetString("username")
|
|
host := viper.GetString("host")
|
|
token := viper.GetString("token")
|
|
|
|
if host != "" && token != "" && username != "" {
|
|
println("Logging in...")
|
|
err := login(host, username, token)
|
|
if err != nil {
|
|
println("Could not log in:", err)
|
|
} else {
|
|
println("Logged in!")
|
|
SaveConfig()
|
|
return
|
|
}
|
|
}
|
|
|
|
println()
|
|
println("A host name is required.")
|
|
host = prompt.Input(prompt.WithPrefix("Host: "), prompt.WithInitialText(host))
|
|
if host == "" {
|
|
return
|
|
}
|
|
viper.Set("host", host)
|
|
|
|
println()
|
|
println("A username is required.")
|
|
username = prompt.Input(prompt.WithPrefix("Username: "), prompt.WithInitialText(username))
|
|
if username == "" {
|
|
return
|
|
}
|
|
viper.Set("username", username)
|
|
|
|
println()
|
|
println("A token is required.")
|
|
token = prompt.Input(prompt.WithPrefix("Token: "), prompt.WithInitialText(token))
|
|
if token == "" {
|
|
return
|
|
}
|
|
viper.Set("token", token)
|
|
}
|
|
}
|
|
|
|
func login(host, username, token string) error {
|
|
var err error
|
|
tp := jira.BasicAuthTransport{
|
|
Username: username,
|
|
Password: token,
|
|
}
|
|
jiraClient, err = jira.NewClient(tp.Client(), host)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, _, err = jiraClient.User.GetSelf()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func noSuggestions(doc prompt.Document) []prompt.Suggest {
|
|
return make([]prompt.Suggest, 0)
|
|
}
|