Question

I'm trying to create an autocomplete script for use with fish; i'm porting over a bash completion script for the same program.

The program has three top level commands, say foo, bar, and baz and each has some subcommands, just say a b and c for each.

What I'm seeing is that the top level commands auto complete ok, so if I type f I'm getting foo to autocomplete, but then if I hit tab again to see what it's sub commands are, i see foo, bar, baz, a, b, c and it should just be a, b, c

I am using as a reference the git completion script since it seems to work right. I am also using the git flow script as a reference as well.

I think this is handled in the git completion script by:

function __fish_git_needs_command
  set cmd (commandline -opc)
  if [ (count $cmd) -eq 1 -a $cmd[1] = 'git' ]
    return 0
  end
  return 1
end

Which makes sense, you can only use the completion if there is a single arg to the command, the script itself; if you use that as the condition (-n) for the call to complete on the top level commands, I think the right thing would happen.

However, what I'm seeing is not the case. I copied that function over to my script, changed "git" appropriately, and did not have any luck.

The trimmed down script is as follows:

function __fish_prog_using_command
  set cmd (commandline -opc)
  set subcommands $argv
  if [ (count $cmd) = (math (count $subcommands) + 1) ]
    for i in (seq (count $subcommands))
      if not test $subcommands[$i] = $cmd[(math $i + 1)]
        return 1
      end
    end
    return 0
  end
  return 1
end

function __fish_git_needs_command
  set cmd (commandline -opc)
  set startsWith (echo "$cmd[1]" | grep  -E 'prog$')
  # there's got to be a better way to do this regex, fish newb alert
  if [ (count $cmd) = 1 ]
    # Is this always false? Is this the problem?
    if [ $cmd[1] -eq $cmd[1] ]
      return 1
    end
  end

  return 0
end

complete --no-files -c prog -a bar -n "__fish_git_needs_command"

complete --no-files -c prog -a foo -n "__fish_git_needs_command"

complete --no-files -c prog -a a -n "__fish_prog_using_command foo" 
complete --no-files -c prog -a b -n "__fish_prog_using_command foo" 
complete --no-files -c prog -a c -n "__fish_prog_using_command foo" 

complete --no-files -c prog -a baz -n "__fish_git_needs_command" 

Any suggestions on how to make this work is much appreciated.

Was it helpful?

Solution

I guess you are aware that return 0 means true and that return 1 means false?

From your output it looks like your needs_command function is not working properly, thus showing bar even when it has subcommands.

I just tried the following code and it works as expected:

function __fish_prog_needs_command
  set cmd (commandline -opc)
  if [ (count $cmd) -eq 1 -a $cmd[1] = 'prog' ]
    return 0
  end
  return 1
end

function __fish_prog_using_command
  set cmd (commandline -opc)
  if [ (count $cmd) -gt 1 ]
    if [ $argv[1] = $cmd[2] ]
      return 0
    end
  end
  return 1
end

complete -f -c prog -n '__fish_prog_needs_command' -a bar

complete -f -c prog -n '__fish_prog_needs_command' -a foo
complete -f -c prog -n '__fish_prog_using_command foo' -a a
complete -f -c prog -n '__fish_prog_using_command foo' -a b
complete -f -c prog -n '__fish_prog_using_command foo' -a c

complete -f -c prog -n '__fish_prog_needs_command' -a baz

Output from completion:

➤ prog <Tab>
bar  baz  foo
➤ prog foo <Tab>
a  b  c
➤ prog foo

Is this what you want?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top