Git Product home page Git Product logo

complete's Introduction

complete

Package complete is everything for bash completion and Go.

The main development is done on the master branch, please follow the link to see an up to dat readme.

The default branch is the v1 branch for backward compatibility with Old libraries and compilers.

complete's People

Contributors

acomagu avatar adamslevy avatar dadgar avatar deleplace avatar divan avatar gechr avatar goreadme[bot] avatar josharian avatar linux4life798 avatar lucapette avatar posener avatar santosh653 avatar sethvargo avatar thomshutt avatar vadmeste avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

complete's Issues

Help with the self example

  1. go get

  2. gocomplete -install

  3. cd ..example/self && go run main.go -complete

  4. $ self [Tab] โŒ

compgen:96: no such file or directory: /var/folders/80/gh9snl2d35bcgh166p7jqs940000gn/T/go-build209898158/command-line-arguments/_obj/exe/main

Why can't I run exec.Command("app do something") call inside custom predictor?

I would like to predict not hardcoded options but pull them from daemon every time.
For example I input command app user remove, click TAB, and cli would offer me list of users which pulled by calling exec.Command("cli-get-users')

type ppred struct{}

func (y ppred) Predict(prefix string) []string {
	dateCmd := exec.Command("app", "user", "list")
	dateOut, err := dateCmd.Output()
	if err != nil {
		// handle error
	}
	s := strings.Split(strings.TrimSpace(string(dateOut)), "\n")
	return predict.Set(s).Predict(prefix)
}

Output is always empty, but when I run this code inside unit test, output is present and we're all good.
If this is expected behaviour please someone explain or point me to explanation why it's not working.

[Proposal] Add IsInstalled API to posener/complete/cmd/install

Hey,

I want from my tool which is using posener/complete to automatically show a yes/no prompt to request user's consent to install bash completion (or others).

However it seems there is no way to avoid to show that prompt when completion is already installed. It seems the only way to do that is to to add IsInstalled() API.

I can send a PR for that if my proposal is accepted.

gocomplete: stderr output jumbles up the prompt

Repro

  1. Follow the gocomplete installation procedure as detailed in the documentation.
  2. Type go test /bi and press Tab once to trigger shell autocompletion.

What is expected to happen

The line is completed as go test /bin/ . There is no additional output.

What actually happens

The prompt is filled with diagnostic messages. On my system it looks like this:

$ go test /bi2021/04/06 12:56:04 failed importing directory /bin: no buildable Go source files in /bin
2021/04/06 12:56:04 failed importing directory /boot: no buildable Go source files in /boot
2021/04/06 12:56:04 failed importing directory /cdrom: no buildable Go source files in /cdrom
2021/04/06 12:56:04 failed importing directory /dev: no buildable Go source files in /dev
2021/04/06 12:56:04 failed importing directory /etc: no buildable Go source files in /etc
2021/04/06 12:56:04 failed importing directory /home: no buildable Go source files in /home
2021/04/06 12:56:04 failed importing directory /lib: no buildable Go source files in /lib
2021/04/06 12:56:04 failed importing directory /lib32: no buildable Go source files in /lib32
2021/04/06 12:56:04 failed importing directory /lib64: no buildable Go source files in /lib64
2021/04/06 12:56:04 failed importing directory /lost+found: open /lost+found: permission denied
2021/04/06 12:56:04 failed importing directory /media: no buildable Go source files in /media
2021/04/06 12:56:04 failed importing directory /mnt: no buildable Go source files in /mnt
2021/04/06 12:56:04 failed importing directory /opt: no buildable Go source files in /opt
2021/04/06 12:56:04 failed importing directory /proc: no buildable Go source files in /proc
2021/04/06 12:56:04 failed importing directory /root: open /root: permission denied
2021/04/06 12:56:04 failed importing directory /run: no buildable Go source files in /run
2021/04/06 12:56:04 failed importing directory /sbin: no buildable Go source files in /sbin
2021/04/06 12:56:04 failed importing directory /snap: no buildable Go source files in /snap
2021/04/06 12:56:04 failed importing directory /srv: no buildable Go source files in /srv
2021/04/06 12:56:04 failed importing directory /sys: no buildable Go source files in /sys
2021/04/06 12:56:04 failed importing directory /tmp: no buildable Go source files in /tmp
2021/04/06 12:56:04 failed importing directory /usr: no buildable Go source files in /usr
2021/04/06 12:56:04 failed importing directory /var: no buildable Go source files in /var
2021/04/06 12:56:04 failed importing directory /: no buildable Go source files in /
n/ 

It's not that difficult to find your bearings and work from the assumption that the command was completed as expected (as described earlier) in this trivial case, but it becomes particularly annoying when you are in the middle of a more complex invocation, such as a build or a tool command with multiple flags, options and other parameters.

Cause

A false assumption is made that all errors are always relevant to the end user and therefore everything should be dumped to stderr without distinction.

Consider making a new patch release

Consider tagging a new patch release as v1.1.2 so that people still using the dep tool will clearly know that they can pull in a new version that includes the minor changes that have been made since 1.1.1.

gocomplete go.mod still broken

tv@dark ~$ mkdir z
tv@dark ~$ cd z
tv@dark ~/z$ go mod init m
go: creating new go.mod: module m
tv@dark ~/z$ go get github.com/posener/complete/gocomplete
go: finding github.com/posener/complete/gocomplete latest
package github.com/posener/complete/gocomplete: unknown import path "github.com/posener/complete/gocomplete": ambiguous import: found github.com/posener/complete/gocomplete in multiple modules:
	github.com/posener/complete v1.1.2 (/home/tv/go/pkg/mod/github.com/posener/[email protected]/gocomplete)
	github.com/posener/complete/gocomplete v0.0.0-20190609060259-60e9d0a23799 (/home/tv/go/pkg/mod/github.com/posener/complete/[email protected])
[EXIT:1] tv@dark ~/z$

At this point, you'd be better off removing gocomplete/go.* completely. It can be part of the parent module.

Go 1.16 beta1: panic: unexpected call to os.Exit(0) during test

Golang 1.16 introduced a change that makes the test fail:


Testing    in: /builddir/build/BUILD/complete-2.0.1-alpha.13/_build/src
         PATH: /builddir/build/BUILD/complete-2.0.1-alpha.13/_build/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin
       GOPATH: /builddir/build/BUILD/complete-2.0.1-alpha.13/_build:/usr/share/gocode
  GO111MODULE: off
      command: go test -buildmode pie -compiler gc -ldflags " -X github.com/posener/complete/v2/version=2.0.1~alpha.13 -extldflags '-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld  '"
      testing: github.com/posener/complete/v2
github.com/posener/complete/v2
PASS
ok  	github.com/posener/complete/v2	0.007s
github.com/posener/complete/v2/compflag
invalid value "3" for flag -a: not in allowed values: 1,2
Usage:
  -a value
    	
invalid value "3" for flag -a: not in allowed values: 1,2
Usage:
  -a value
    	 (default 0)
invalid value "1h" for flag -a: not in allowed values: 1s,1m
Usage:
invalid value "x" for flag -a: bad value for Int flag
  -a value
    	 (default 0s)
invalid value "1" for flag -a: bad value for Duration flag
Usage:
  -a value
    	 (default 0s)
Usage:
  -a value
    	 (default 0)
PASS
ok  	github.com/posener/complete/v2/compflag	0.006s
github.com/posener/complete/v2/gocomplete
run
--- FAIL: Example (0.00s)
panic: unexpected call to os.Exit(0) during test [recovered]
	panic: unexpected call to os.Exit(0) during test

It is maybe related to https://tip.golang.org/doc/go1.16#go-test

golang/go#29062
https://go-review.googlesource.com/c/go/+/250977/

Bring flag arguments to subcommand?

Is there any way for a subcommands' prediction to get its parents flags?

For example

adb -s FA81Y1A02186 uninstall com.blabla

-s flag correctly predicts FA81Y1A02186.

However, if i in the handler want to predict what packages to uninstall, i need the predicted flag value from before. Because i want to query the specific device for packages that are installed.
Currently i can't. Maybe i've missed something.

gocomplete: test failures are supressed

Repro

Test the gocomplete package with the following applied:

diff --git a/gocomplete/tests_test.go b/gocomplete/tests_test.go
index 750147a..c7521ef 100644
--- a/gocomplete/tests_test.go
+++ b/gocomplete/tests_test.go
@@ -21,7 +21,7 @@ func TestPredictions(t *testing.T) {
 		{
 			name:      "predict tests ok",
 			predictor: predictTest,
-			want:      []string{"TestPredictions", "Example"},
+			want:      []string{"bork", "bork"},
 		},
 		{
 			name:      "predict benchmark ok",

Ought v. Is

You would expect the tests to fail hard, yet they seem to still pass.
$ go test ./gocomplete/
ok      github.com/posener/complete/v2/gocomplete       0.003s
In reality they do fail, but it simply isn't reported.
$ go test -v ./gocomplete/
=== RUN   TestPredictions
=== PAUSE TestPredictions
=== CONT  TestPredictions
=== RUN   TestPredictions/predict_tests_ok
    tests_test.go:37: Failed TestPredictions/predict_tests_ok: got: ["Example" "TestPredictions"], want: ["bork" "bork"]
=== RUN   TestPredictions/predict_benchmark_ok
--- FAIL: TestPredictions (0.00s)
    --- FAIL: TestPredictions/predict_tests_ok (0.00s)
    --- PASS: TestPredictions/predict_benchmark_ok (0.00s)
=== RUN   Example
run
--- FAIL: Example (0.00s)
got:

want:
run
FAIL
ok      github.com/posener/complete/v2/gocomplete       0.004s

Cause

The package testing uses os.Exit all over the place, and, as of 5d9f7f1, all those uses, including test failure reporting, are effectively broken once the gocomplete.Example test runs.

Omit trailing space from completion

When writing completion function in bash you can use compopt -o nospace to omit the trailing space from completed arguments.

How could something like this be achieved using this library? Calling out to compopt from the predict function doesn't work.

Flags are over-recommended

Global flags should not be valid/recommended after a subcommand, should they? Currently in s5cmd/develop I'm reading COMP_LINE and checking if any subcommands (well, "non-flags") are specified, if they are, I reset Command.Flags to nil (before the complete.New() call) to remedy this. Also, some flags can be mutually exclusive. So, a way to turn off a specific flag might be handy and help with these cases. Flags are also recommended after arguments, which doesn't seem like a common/intuitive use to me.

To help with these issues, maybe support a flag "callback" to dynamically disable a particular flag? Where one might check for Args.Last and if there's an argument (non-flag) there (or a mutually-exclusive option is already specified) disable the flag essentially making the completion smarter. (I might make a PR for this if you like, if you don't have something better in mind that is...)

How to write shell completion function in Go

I am getting started with this project so I apologize for such a basic question.

For example the following is a zsh completion function for command foo:

#compdef _foo foo
compadd first second third fourth

So, if we type foo <tab> in the zsh terminal, it suggests first second third fourth.

How can I do this using complete?

'Sub:' and 'Flags:' don't seem to work together.

var force = flag.String("f", "", "force")
...

// Auto completion
cmd := &complete.Command{
	Sub: map[string]*complete.Command{
		"update": {
			Sub: offPred,
			Flags: map[string]complete.Predictor{
				"f": predict.Nothing,
			},
		},
	},
}
cmd.Complete("<cmd>")

On the latest version, when I execute this code, only Sub: will get suggested. However, if I remove the Sub: entirely, then Flags: show up. I have the feeling I'm doing it wrong, but I've boiled it down to this, at least.

PS: I'm using Kong as well, and the -h flag always shows up automatically (not sure if that's Kong or this package), but that flag shows up fine.

I have not been able to get it to work

The instruction is quite confusing for me. Here is what I did. I wrote a piece of code very similar to the example code on the doc page, which generated a binary let's call "autocomplete", then I run "./autocomplete -install" and install it. Then I run my command as usual, and nothing was different. There has been an added line to my bashrc. Is there anything I am doing wrong?

Add support for COMP_POINT environment variable.

Currently the completion assumes that the cursor is on the end of the completion line.
There is an environment variable COMP_POINT which indicates the cursor location, which this library should use.

[Proposal] Add new API to pass options to complete command

Hey.

Currently, using posener/complete does not automatically escape spaces in bash.

I think the best solution of this is to add a new API which pass options to complete command, such as:

  • -o filenames to automatically escapes spaces
  • -o nospace related to this issue #87

What do you think @posener ?

Add support for completing short flags (-x)

I have a setup like so:

Flags: map[string]complete.Predictor{
  "o": predict.Nothing,
  "upload-pack": predict.Nothing,
  ...
}

Now when I type a command like <cmd> -- [TAB] I see the below

Screen Shot 2020-10-05 at 12 15 48 AM

I would expect to only see the long flags

Support for COMP_POINT seems to have broken completionโ€ฆ


goroutine 1 [running]:
.../vendor/github.com/posener/complete.(*Complete).Complete(0xc00038c690, 0x0)
	.../vendor/github.com/posener/complete/complete.go:67 +0x634
...
panic: runtime error: slice bounds out of range```

on tabbing for completion right after the name of the command. I haven't investigated closer but reverting to `1.1.2` fixes the issue.

Autocomplete subcommands even with nonexistent command

Hey,

I noticed this bug when helping out with the other PRs. The autocomplete library can autocomplete a subcommand even if the given arguments wouldn't result in a valid command.

The issue stems from here: https://github.com/posener/complete/blob/master/command.go#L75-L76

For example nomad job has these subcommands:

$ nomad job
This command is accessed by using one of the subcommands below.

Subcommands:
    deployments    List deployments for a job
    dispatch       Dispatch an instance of a parameterized job
    history        Display all tracked versions of a job
    promote        Promote a job's canaries
    revert         Revert to a prior version of the job
    status         Display status information about a job

If I write: $ nomad job nonexistent stat<tab> it will autocomplete which is incorrect.

It is because the loop iterates till it finds a match, but really should give up if the argument leads to an incorrect subcommand.

Autocompletion for multiple positional arguments when flags are present

I ran into troubles when implementing autocompletion for multiple positional arguments if flags are present.

Scenario:

  • command with multiple positional arguments (required or optional, doesn't matter)
  • command also accepts flags

In order to implement autocompletion for both position arguments, you need to check how many args have already been completed (via args.Completed). Here's an example from terraform (and the implementation).

And here's another example from my own CLI package.

These work fine when no flags are present, but it breaks down if there's flags because those flags will be included in args.Completed which means you can't naively just check the length of the array.

Example:

trellis deploy prod<tab>
# autocompletes to production

trellis deploy production exam<tab>
# autocompletes to example.com

trellis deploy --bran<tab>
# autocompletes to branch

trellis deploy --branch=foo prod<tab>
# does not autocomplete properly

Solution

I think I've been able to fix this by passing in the flag.FlagSet and parsing the args on every prediction. Then instead of checking the length of args.Completed, you use the length of parsed positional args. However, this adds a lot of complexity and seemed non-intuitive. Here's my solution so far: https://github.com/roots/trellis-cli/blob/dd2156bf2c923978ef3866c2b00517d903553cc8/trellis/complete.go#L38-L55

Since args and flags are handled separately in complete.Command, I'd kind of expect that the predict function just for args wouldn't include the flags. Or if it did (because that might be useful in case positional args depend on flags?), complete.Args would at least handle this automatically and provide both separately?

Idea

This would be a breaking change, but could this package move completed flags out of args.Completed and into args.FlagsCompleted? Or maybe Predict could be called like this for arguments:

c.Predict(args, flags)

Though that seems much more breaking. I'm probably missing other solutions as well though ๐Ÿ˜…

The way of installation was chenged

Now, the way of installation of Golang's pacage is as follow.

go install github.com/posener/complete/v2/gocomplete@latest

Can I modify a README of this repository?

Autocomplete subcommand that has a same name as its parent doesn't work

Consider this structure

run := complete.Command{
	Sub: complete.Commands{
		"build": complete.Command{
			Sub: complete.Commands{
				"next":    complete.Command{},
				"forward": complete.Command{},
				"build":   complete.Command{},
			},
		},
	},
}

complete.New("app", run).Run()

When you try app build it should suggests three sub commands next, forward and build but it suggests nothing.

How to keep default bash filename completion for positional argument?

Hi, I really like how easily complete allows to add completion to CLI tools using flag but since I use it, I have lost the classic bash completion on filenames for positional arguments.

Take this example:

package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/posener/complete/v2"
)

func main() {
	printJSON := flag.Bool("json", false, "prints the filename in JSON")

	complete.CommandLine()
	flag.Parse()

	if flag.NArg() < 1 {
		fmt.Printf("File argument is missing\n\n")
		flag.Usage()
		os.Exit(1)
	}

	if *printJSON {
		fmt.Println("{\"filename\": \"" + flag.Arg(0) + "\"}")
	} else {
		fmt.Println("File: " + flag.Arg(0))
	}
}

Without the complete.CommandLine() line, I do not get completion for the -json flag but my positional argument is well completed by bash.
But with this line, I do not get completion anymore.

Is there anything to get the file completion behavior back?

Thank you

zsh completions on <enter>

Hi there!

First, thank you for the great library! I'm encountering a weird issue that only seems present on zsh. Here's a quick program to reproduce:

package main

import (
	"github.com/posener/complete"
)

func main() {
	run := complete.Command{
		Args: complete.PredictFiles("*"),
	}
	complete.New("playground", run).Run()
}

Compile this and install the shell completions. On my shell (zsh), when I run this command and press <tab>, I correctly get a list of files. However, when I select a folder and press <enter>, a space is inserted and prediction stops.

Here's the same binary, same terminal, using /bin/bash instead of /bin/zsh:

As you can see, selecting an item in zsh appears to move to the next argument where bash continues to wait for the next filepath.

Do you have any ideas here? I've done a complete uninstall of zsh and disabled all plugins and still see the same behavior. Have you seen this before?

gocomplete -install doesn't appear to do anything

I did:

$ go get -u github.com/posener/complete/gocomplete
$ gocomplete -install
# restart shell
$ go bui<tab>

Result: No completion.

From a cursory scan of the source, gocomplete -install should have prompted me, but it did not. Is it possible that the completer for go install is somehow interfering with the request for installation?

Thanks, and looking forward to using this.

Complete packages names?

Hello, I am pretty exicted by the "Complete packages names" feature, which is exactly what I'm looking for.
I assume it should work on any fully qualified package name that resides inside $GOPATH (which would default to ~/go if $GOPATH is not set).

Unfortunately, I couldn't make it work:
go build github.c๐Ÿ”‚
go test github.com/gorilla/mu๐Ÿ”‚

...no results. I have tried with and without GOPATH set, even after starting new bash.
Any idea?

go tool subcommand completion missing

$ go tool com<tab>
$ go tool pp<tab>

This should autocomplete to go tool compile and go tool pprof. And ideally also understand the subcommands' flags (of which there are admittedly many). But just completing the subcommands themselves would be a nice start.

Support specifying the completion command

As an alternative to inferring the completion command from the binary, allow the command to be specified.

This is necessary for using a subcommand as a the completion command.

Module aware go completion

I use this package's go completion daily and I really appreciate it. However the completion suggestions for packages is both limited and now outdated as it relies on GOPATH, which is effectively deprecated.

I would like the go completion to take advantage of go list to obtain a module aware list of suggestions. This can even be used to greatly improve the use of go doc and complete not just package name but also symbols from the package. The suggestions can even take into account the -u flag and offer unexported completion suggestions as well.

This can fall back to searching the module cache if no matching name is in the local projects go.mod file, and finally it could fall back to searching $GOPATH/src/ for package name completions.

I did a little research and discovered that there is no package that exposes the same functionality as go list however it has well defined JSON output option so parsing the output is trivial.

I am interested in submitting a PR for this but wanted to discuss it in an issue first.

Subcommands that share a name with a parent will not autocomplete

The title isn't great. I'll explain. First, thanks for a great library. ๐ŸŽ‰

I have a diff at the bottom of this issue with a fix, but I'm not sure how you want to unit test it so I didn't open a PR. Its a one-line fix.

The Problem

We have a CLI with the following two commands:

  • nomad job status
  • nomad status

They each implement their own arg autocompletion func. However, we noticed that only the outer one was ever being called. i.e. when you did nomad job status <tab>, it was returning the same output for nomad status <tab>. Further confusing: it seemed to call both autocomplete funcs, but only outputted the outer one.

We expected the behavior to only call the inner one.

A failing structure is shown below (where each Args PredictFucn outputs a different thing):

complete.Command{
    Sub: {
        "job": {
            Sub: {
                "status": {
                    Sub:         {},
                    Flags:       {},
                    GlobalFlags: {},
                    Args:        complete.PredictFunc {...},
                },
            },
            Flags:       {},
            GlobalFlags: {},
            Args:        nil,
        },
        "status": {
            Sub:         {},
            Flags:       {},
            GlobalFlags: {},
            Args:        complete.PredictFunc {...},
        },
    },
    Flags:       {},
    GlobalFlags: {},
    Args:        nil,
}

The Solution

I found the solution is to set only = true in c.predict when there is a subcommand found. This properly short-circuits the search. Otherwise, a parent matching command is found and overwrites any results. We also don't want the results merged, since the parent command does something totally different.

Here is the diff:

diff --git a/command.go b/command.go
index eeeb9e0..42b7f43 100644
--- a/command.go
+++ b/command.go
@@ -87,6 +87,7 @@ func (c *Command) predict(a Args) (options []string, only bool) {
        // if a sub command was entered, we won't add the parent command
        // completions and we return here.
        if subCommandFound {
+         only = true
                return
        }

We'd love to see this fixed!

Again, thanks for a great library. We're rolling this out to all HashiCorp tooling and its been great so far. This is the first bug we've ran into.

Error when installing to msys2 bash

Thanks for making this lib it's quite useful. Please see the error and potential problem outlined below.

10:21:07 chrome@Beast src โ†’ bit complete
install completion for bit? y
installing...
regexp: Compile(`^complete -C C:\Users\chrome\go\bin\bit.exe bit$`): error parsing regexp: invalid escape sequence: `\U`

goroutine 1 [running]:
runtime/debug.Stack(0xf51840, 0xc000006018, 0xc00011cc78)
        C:/Dev/Go/src/runtime/debug/stack.go:24 +0xa5
github.com/chriswalz/bit/cmd.HandleExit()
        C:/Users/chrome/go/pkg/mod/github.com/chriswalz/[email protected]/cmd/util.go:320 +0xea
panic(0xe0cfe0, 0xc0000533f0)
        C:/Dev/Go/src/runtime/panic.go:965 +0x1c7
regexp.MustCompile(0xc000376510, 0x30, 0x1)
        C:/Dev/Go/src/regexp/regexp.go:311 +0x15f
github.com/chriswalz/complete/v3/install.lineInFile(0xc00001cd38, 0x17, 0xc0003764b0, 0x2e, 0x2)
        C:/Users/chrome/go/pkg/mod/github.com/chriswalz/complete/[email protected]/install/utils.go:12 +0x12c
github.com/chriswalz/complete/v3/install.bash.IsInstalled(0xc00001cd38, 0x17, 0xea613a, 0x3, 0xc000376450, 0x1e, 0x2)
        C:/Users/chrome/go/pkg/mod/github.com/chriswalz/complete/[email protected]/install/bash.go:15 +0xfc
github.com/chriswalz/complete/v3/install.bash.Install(0xc00001cd38, 0x17, 0xea613a, 0x3, 0xc000376450, 0x1e, 0x0, 0x0)
        C:/Users/chrome/go/pkg/mod/github.com/chriswalz/complete/[email protected]/install/bash.go:19 +0x77
github.com/chriswalz/complete/v3/install.Install(0xea613a, 0x3, 0xc00011d350, 0xe)
        C:/Users/chrome/go/pkg/mod/github.com/chriswalz/complete/[email protected]/install/install.go:66 +0xf6

According to this comment the problem is due to:

  1. https://github.com/posener/complete/blob/master/install/bash.go#L36

  2. https://github.com/posener/complete/blob/master/install/bash.go#L15

  3. https://github.com/posener/complete/blob/master/install/utils.go#L12

The code seems to assume that cmd or bin doesn't contain any regexp characters. The 3. probably should escape all those characters. It's weird that it's using regexps for that in the first place.

Should this work?

I build the below command, run ./<cmd> -complete.
Then I type (in bash) ./<cmd> -na and expect it to auto fill 'me'.
Should that work?

int main(){
var name string
flag.StringVar(&name, "name", "", "Give your name")

cmp := complete.New(
	flag.Arg(0),
	complete.Command{
		Sub: complete.Commands{
				"sadface": complete.Command{

				},
		},
		Flags: complete.Flags{
			"name": complete.PredictAnything,
		},
	},
)

cmp.AddFlags(nil, "complete", "uncomplete")

flag.Parse()

fmt.Printf("%s %s %s", flag.Args()...)
if cmp.Run() {
	return
}

if name == "" {
	fmt.Println("Your name is missing")
	os.Exit(1)
}

fmt.Println("Hi,", name)

}

Install without using Flags

I would prefer to use a completely different approach to exposing the install/uninstall than with the flags package. I'm using a completely different package for building CLI apps, and would like to integrate the output of this framework with that other package by simply Printing/Sprinting the output to wherever the user wants.

Sensible line wrap length for comments

Feel free to close this immediately for being pedantic, however the comments in this package are not line wrapped at a sensible length. This is extremely annoying to work with in a terminal editor. This is totally a style choice, but I hate having to read comments in vim that go beyond 80 chars in length on a single line.

Global flags

I recently switched to the current master branch of complete. Previously I was able to define global flags and have them suggested before I input any sub commands. Now they are skipped even though they are defined as Flags in the main command definition. I also define a Sub in the main command and noticed that the complete() function only seems to suggest leaf command options if there are no sub commands defined. I would like to be able to define global flags such as --verbose and have them suggested.

case len(c.SubCmdList()) == 0:
		// No sub commands, parse flags and positional arguments.
		return c.suggestLeafCommandOptions(), nil

complete: the output of complete.Complete() cannot be captured

Repro

Test the gocomplete package. The Example test fails.
$ go test ./gocomplete/
run
--- FAIL: Example (0.00s)
got:

want:
run
FAIL
FAIL    github.com/posener/complete/v2/gocomplete       0.004s
FAIL
Implementing an analogous test in the complete package confirms this as a problem in the latter.
diff --git a/complete_test.go b/complete_test.go
index 3a0809f..e26522e 100644
--- a/complete_test.go
+++ b/complete_test.go
@@ -3,6 +3,7 @@ package complete
 import (
 	"io/ioutil"
 	"os"
+	"strconv"
 	"testing"
 
 	"github.com/posener/complete/v2/internal/arg"
@@ -214,6 +215,42 @@ func TestComplete(t *testing.T) {
 	}
 }
 
+// ExampleComplete_outputCapturing demonstrates the ability to capture
+// the output of Complete() invocations, crucial for integration tests.
+func ExampleComplete_outputCapturing() {
+	// a stringLookup function maps one string to another.
+	// os.GetEnv is an instance of such a function.
+	type stringLookup = func(string) string
+
+	// promptEnv returns stringLookup func that emulates the environment
+	// variables a shell would set when its prompt has the given contents.
+	var promptEnv = func(contents string) stringLookup {
+		return func(key string) string {
+			switch key {
+			case "COMP_LINE":
+				return contents
+			case "COMP_POINT":
+				return strconv.Itoa(len(contents))
+			}
+			return ""
+		}
+	}
+
+	defer func(f func(int)) { exit = f }(exit)
+	defer func(f stringLookup) { getEnv = f }(getEnv)
+	exit = func(int) {}
+
+	// This is where the actual example starts:
+
+	cmd := &Command{Sub: map[string]*Command{"bar": {}}}
+	getEnv = promptEnv("foo b")
+
+	Complete("foo", cmd)
+
+	// Output:
+	// bar
+}
+
 type set []string
 
 func (s set) Predict(_ string) []string {
$ go test -run=^Example -v
=== RUN   ExampleComplete_outputCapturing
bar
--- FAIL: ExampleComplete_outputCapturing (0.00s)
got:

want:
bar
FAIL
FAIL    github.com/posener/complete/v2  0.003s
FAIL

Expectation ^ reality

That's an easy one: everyone would like their tests to never fail, but these ones do. ๐Ÿ˜ž

Cause

The root cause lies in the line 54 here:

complete/complete.go

Lines 52 to 56 in 002575c

getEnv = os.Getenv
exit = os.Exit
out io.Writer = os.Stdout
in io.Reader = os.Stdin
)

It defines a global var out io.Writer, assigned to at the package initialization (this article seems a bit more explicit on the sequence).

This means that by the time tests (in this case, testing.runExample(), to be precise) finally get around to capturing stdout, it has already been effectively hard-coded to the initial value throughout the complete package. Which in turn means that nothing outside of complete can ever change where the output goes to, therefore no tests in the world (apart from the complete package itself) can ever see what's really going on with the output.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.