complete icon indicating copy to clipboard operation
complete copied to clipboard

How to keep default bash filename completion for positional argument?

Open romainreignier opened this issue 3 years ago • 3 comments

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

romainreignier avatar Dec 29 '20 18:12 romainreignier

Hi there,

I am not aware for any fall back option. If there is such, it will be nice to have it. Other than that, I can give you two options:

  1. Try the posener/cmd library, where you can easily define completion for positional arguments.
  2. Use the Command.Args option

posener avatar Dec 29 '20 20:12 posener

Hi @posener

Thank you for your reply.

The solution 1. seems the simpler.

I have then modified my minimal example to:

package main

import (
	"fmt"
	"os"

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

func main() {
	root := cmd.New()
	printJSON := root.Bool("json", false, "prints the filename in JSON")
	args := root.Args("<input_file>", "File to print the name", predict.OptPredictor(predict.Files("*")))
	root.Parse()

	// Could be remplaced with args = make(cmd.ArgsStr, 1) and ArgsVar()
	if len(*args) < 1 {
		fmt.Printf("File argument is missing\n\n")
		root.Usage()
		os.Exit(1)
	}

	if *printJSON {
		fmt.Println("{\"filename\": \"" + (*args)[0] + "\"}")
	} else {
		fmt.Println("File: " + (*args)[0])
	}
}

Without the --json flag, the positional argument is completed but when the boolean flag is used, the file completion does not work.

What would be the correct usage?

Thank you

romainreignier avatar Dec 30 '20 09:12 romainreignier

Hi

Right, it seems to be a bug... :disappointed:

$ ./test <tab>
./       go.mod   go.sum   -h       -json    main.go  test

But ./test -json<tab> adds space, and then ./test -json <tab> adds dash, and then:

$ ./test -json -
-h     -json 

posener avatar Dec 30 '20 14:12 posener