Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,15 @@ func Execute() {
os.Exit(1)
}
}

// ExecuteShell: Interactive shell
func ExecuteShell(shellStarter func(*cobra.Command)) {
// Init Config
err := conf.InitConfig("config.yml")
if err != nil {
logrus.Errorln(err)
os.Exit(1)
}
// Exec shell
shellStarter(rootCmd)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
require (
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down Expand Up @@ -51,6 +55,7 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/vbauerster/mpb/v8 v8.7.2 h1:SMJtxhNho1MV3OuFgS1DAzhANN1Ejc5Ct+0iSaIkB14=
github.com/vbauerster/mpb/v8 v8.7.2/go.mod h1:ZFnrjzspgDHoxYLGvxIruiNk73GNTPG4YHgVNpR10VY=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
Expand Down
112 changes: 112 additions & 0 deletions internal/shell/shell.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package shell

import (
"fmt"
"os"
"strings"

"github.com/chzyer/readline"
"github.com/spf13/cobra"
)

// Start starts the interactive shell
func Start(rootCmd *cobra.Command) {
fmt.Println("PikPak CLI Interactive Shell")
fmt.Println("Type 'help' for available commands, 'exit' to quit")
fmt.Println()

// Create readline instance
// TODO: we can add path here: pikpak {path} >.
l, err := readline.New("pikpak > ")
if err != nil {
fmt.Fprintf(os.Stderr, "Error initializing readline: %v\n", err)
return
}
defer l.Close()

for {
input, err := l.Readline()

// Handle EOF (Ctrl+D)
if err == readline.ErrInterrupt {
continue
}

if err != nil {
// This is EOF
fmt.Println("\nBye~!")
break
}

input = strings.TrimSpace(input)

if input == "" {
continue
}

if input == "exit" || input == "quit" {
fmt.Println("Bye~!")
break
}

if input == "help" {
rootCmd.Help()
continue
}

// Parse the args and set them to rootCmd
args := parseShellArgs(input)
rootCmd.SetArgs(args)

// Directly use pre-defined Execute function
// TODO: Need to be updated if cd command is supported.
if err := rootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
}
rootCmd.SetArgs([]string{}) // Reset for next iteration
}
}

// parseShellArgs parses shell-like arguments
func parseShellArgs(input string) []string {
var args []string
var current strings.Builder
inDoubleQuote := false
inSingleQuote := false

for i := 0; i < len(input); i++ {
ch := input[i]

switch ch {
case '"':
if inSingleQuote {
current.WriteByte(ch)
} else {
inDoubleQuote = !inDoubleQuote
}
case '\'':
if inDoubleQuote {
current.WriteByte(ch)
} else {
inSingleQuote = !inSingleQuote
}
case ' ', '\t':
if inDoubleQuote || inSingleQuote {
current.WriteByte(ch)
} else {
if current.Len() > 0 {
args = append(args, current.String())
current.Reset()
}
}
default:
current.WriteByte(ch)
}
}

if current.Len() > 0 {
args = append(args, current.String())
}

return args
}
15 changes: 13 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
package main

import "github.com/52funny/pikpakcli/cmd"
import (
"os"

"github.com/52funny/pikpakcli/cmd"
"github.com/52funny/pikpakcli/internal/shell"
)

func main() {
cmd.Execute()
// Check if any args
if len(os.Args) == 1 {
cmd.ExecuteShell(shell.Start)
} else {
// If no arg, execute the command directly
cmd.Execute()
}
}