From 1bd404db9429be8e27c64dcf42f59a45f7425199 Mon Sep 17 00:00:00 2001 From: hedy Date: Wed, 6 Dec 2023 09:07:06 +0800 Subject: [PATCH] Use shlex --- client.go | 6 ++++-- cmd.go | 28 ++++++++++++++++++---------- gelim.go | 33 --------------------------------- go.mod | 1 + go.sum | 20 ++------------------ 5 files changed, 25 insertions(+), 63 deletions(-) diff --git a/client.go b/client.go index 0a1cb1b..eca9cf2 100644 --- a/client.go +++ b/client.go @@ -10,6 +10,7 @@ import ( "strings" "git.sr.ht/~adnano/go-xdg" + "github.com/google/shlex" "github.com/manifoldco/ansiwrap" ln "github.com/peterh/liner" "golang.org/x/term" @@ -835,7 +836,8 @@ func (c *Client) GetCommandAndArgs(line string) ( return } - // Rejoin args, split using QuotedFields - args = QuotedFields(strings.Join(args, " ")) + // Rejoin args, split using shlex + // XXX: err is ignored + args, _ = shlex.Split(strings.Join(args, " ")) return } diff --git a/cmd.go b/cmd.go index 5ccb398..e0308b3 100644 --- a/cmd.go +++ b/cmd.go @@ -7,6 +7,8 @@ import ( "os/exec" "strconv" "strings" + + "github.com/google/shlex" ) // Command is the metadata of all (non-meta) commands in the client @@ -40,18 +42,19 @@ func printHelp(style *Style) { minSepSpaceLen := 2 // min space between command and the description // Here comes the fun part // We are now *actually* printing the help - fmt.Println("You can directly enter a url or link-index (number) at the prompt.") - fmt.Println() - fmt.Println("Otherwise, there are plenty of useful commands you can use.") - fmt.Println("Arguments are separated by spaces, and quoting with ' and \" is supported\nlike the shell, but escaping quotes is not support yet.") - fmt.Println() - fmt.Println("You can supply a command name to `help` to see the help for a specific command, like `help tour`.") - fmt.Println() - fmt.Println("Commands:") + fmt.Println(`You can directly enter a url or link-index (number) at the prompt. + +Otherwise, there are plenty of useful commands you can use. Arguments +are separated by spaces, and quoting with ' and " is supported like the +shell, escaping quotes is also supported. + +You can supply a command name to 'help' to see the help for a specific +command, like 'help tour. + +Commands:`) var spacesBetween int for name, cmd := range commands { // TODO: wrap description with... aniswrap? - // also maybe add some colors in the help! if cmd.hidden { continue } @@ -602,7 +605,12 @@ func (c *Client) ClipboardCopy(content string) (ok bool) { c.style.ErrorMsg("please set a clipboard command in config file option 'clipboardCopyCmd'\nThe content to copy will be piped into that command as stdin") return } - parts := strings.Split(c.conf.ClipboardCopyCmd, " ") + parts, err := shlex.Split(c.conf.ClipboardCopyCmd) + if err != nil { + ok = false + c.style.ErrorMsg("Could not parse ClipboardCopyCmd into command and arguments: " + c.conf.ClipboardCopyCmd) + return + } cmd := exec.Command(parts[0], parts[1:]...) stdin, err := cmd.StdinPipe() if err != nil { diff --git a/gelim.go b/gelim.go index 700754b..74aa700 100644 --- a/gelim.go +++ b/gelim.go @@ -30,39 +30,6 @@ var ( quoteFieldRe = regexp.MustCompile("'(.*)'|\"(.*)\"|(\\S*)") ) -// QuotedFields is an alternative to strings.Fields (see: -// https://golang.org/pkg/strings#Fields) that respects spaces between matching -// pairs of quotation delimiters. -// -// For instance, the quoted fields of the string "foo bar 'baz etc'" would be: -// -// []string{"foo", "bar", "baz etc"} -// -// Whereas the same argument given to strings.Fields, would return: -// -// []string{"foo", "bar", "'baz", "etc'"} -func QuotedFields(s string) []string { - submatches := quoteFieldRe.FindAllStringSubmatch(s, -1) - out := make([]string, 0, len(submatches)) - for _, matches := range submatches { - // if a leading or trailing space is found, ignore that - if matches[0] == "" { - continue - } - // otherwise, find the first non-empty match (inside balanced - // quotes, or a space-delimited string) - var str string - for _, m := range matches[1:] { - if len(m) > 0 { - str = m - break - } - } - out = append(out, str) - } - return out -} - // Pager uses `less` to display body // falls back to fmt.Print if errors encountered func Pager(body string, conf *Config) { diff --git a/go.mod b/go.mod index b59d907..a67a24a 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( git.sr.ht/~adnano/go-xdg v0.1.0 github.com/BurntSushi/toml v1.3.2 github.com/fatih/color v1.15.0 + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/manifoldco/ansiwrap v1.1.0 github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect diff --git a/go.sum b/go.sum index 84ace78..9622e83 100644 --- a/go.sum +++ b/go.sum @@ -1,31 +1,22 @@ git.sr.ht/~adnano/go-xdg v0.1.0 h1:UvmVKPmbWHoMGzdfKLvHBGf/Yfp74pqfyJiyu558TB8= git.sr.ht/~adnano/go-xdg v0.1.0/go.mod h1:n3ytgoiOi6MHzs0leTpVOwDI3L8n+M/E8hS0sEPrzFs= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/manifoldco/ansiwrap v1.1.0 h1:NS3ZV8cCh+dG/sM4e4wM0WSMFWHhSuVFNnwtx6qrqyU= github.com/manifoldco/ansiwrap v1.1.0/go.mod h1:2yA5wi1rF9kAuD6RbwON60QdT46zrKhIS+KHbNwwy8U= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/peterh/liner v1.2.1 h1:O4BlKaq/LWu6VRWmol4ByWfzx6MfXc5Op5HETyIy5yg= -github.com/peterh/liner v1.2.1/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/peterh/liner v1.2.2 h1:aJ4AOodmL+JxOZZEL2u9iJf8omNRpqHc/EbrK+3mAXw= github.com/peterh/liner v1.2.2/go.mod h1:xFwJyiKIXJZUKItq5dGHZSTBRAuG/CpeNpWLyiNRNwI= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -33,17 +24,10 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4 h1:UPou2i3GzKgi6igR+/0C5XyHKBngHxBp/CL5CQ0p3Zk= -golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=