Fish shell completions for Pijul (forked from jmgd/pijul-fish-completions)
# developed against pijul 1.0.0-beta.1
# TODO: add pijul tracked file completions instead of stock fish completions

set -l commands add apply archive change channel clone credit diff fork git init key list ls log move mv pull push record remote remove reset tag unrecord help

function __fish_pijul_needs_command
  set -l cmd (commandline -opc)
  set -e cmd[1]
  if set -q cmd[1]
    echo $cmd[1]
    return 1
  end
  return 0
end

function __fish_pijul_seen_command
  set -l cmd (__fish_pijul_needs_command)
  if [ -z "$cmd" ]
    return 1
  end
  contains -- $cmd $argv
  return $status
end

complete -f -c pijul

# global flags
complete -f -c pijul -s h -l help    -d "Print help information"
complete -f -c pijul -s V -l version -d "Print version information"

# pijul add
complete -c pijul -n __fish_pijul_needs_command -a add -d "Adds a path to the tree"
complete -c pijul -n "__fish_pijul_seen_command add" -F
complete -c pijul -n "__fish_pijul_seen_command add" -s f -l force
complete -c pijul -n "__fish_pijul_seen_command add" -s r -l recursive

function __fish_complete_pijul_channels
  # strip out the * from the current channel name
  for line in (pijul channel)
    echo (string split ' ' $line)[-1]
  end
end

function __fish_complete_pijul_changes
  # HASH<tab>MESSAGE
  pijul log --output-format json | jq -r 'map([.hash, .message])[] | @tsv'
end

# pijul apply
complete -c pijul -n __fish_pijul_needs_command -a apply -d "Applies changes to a channel"
complete -c pijul -n "__fish_pijul_seen_command apply" -a "(__fish_complete_pijul_changes)"
complete -c pijul -n "__fish_pijul_seen_command apply" -l channel    -xa "(__fish_complete_pijul_channels)" -d "Apply change to this channel"
complete -c pijul -n "__fish_pijul_seen_command apply" -l deps-only      -d "Only apply the dependencies of this change, not the change itself"
complete -c pijul -n "__fish_pijul_seen_command apply" -l repository -rF -d "Set the repository where this command should run"

function __fish_complete_pijul_remotes
  pijul remote | string trim | cut -d' ' -f2
end

# # pijul archive
complete -c pijul -n __fish_pijul_needs_command -a archive -d "Creates an archive of the repository"
complete -c pijul -n "__fish_pijul_seen_command archive" -l change     -xa "(__fish_complete_pijul_changes)"  -d "Apply these changes after switching to the channel"
complete -c pijul -n "__fish_pijul_seen_command archive" -l channel    -xa "(__fish_complete_pijul_channels)" -d "Use this channel, instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command archive" -s k              -d "Do not check certificates (HTTPS remotes only, this option might be dangerous)"
complete -c pijul -n "__fish_pijul_seen_command archive" -s o          -rF -d "Name of the output file"
complete -c pijul -n "__fish_pijul_seen_command archive" -l prefix     -r  -d "Append this path in front of each path inside the archive"
complete -c pijul -n "__fish_pijul_seen_command archive" -l remote     -xa "(__fish_complete_pijul_remotes)"  -d "Ask the remote to send an archive"
complete -c pijul -n "__fish_pijul_seen_command archive" -l repository -rF -d "Set the repository where this command should run"
# TODO: completions for state argument
complete -c pijul -n "__fish_pijul_seen_command archive" -l state      -r -d "Archive in this state"
complete -c pijul -n "__fish_pijul_seen_command archive" -l umask      -r

# # pijul change
complete -c pijul -n __fish_pijul_needs_command -a change -d "Shows information about a particular change"
complete -c pijul -n "__fish_pijul_seen_command change" -a "(__fish_complete_pijul_changes)"
complete -c pijul -n "__fish_pijul_seen_command change" -l repository -rF -d "Use the repository at PATH instead of the current directory"

# #pijul channel
set -l channel_commands delete new rename switch
complete -c pijul -n __fish_pijul_needs_command -a channel -d "Manages different channels"
complete -c pijul -n "__fish_pijul_seen_command channel" -l repository -rF -d "Set the repository where this command should run"
complete -c pijul -n "__fish_pijul_seen_command channel; and not __fish_seen_subcommand_from $channel_commands" -a delete -d "Delete a channel. The channel must not be the current channel"
complete -c pijul -n "__fish_pijul_seen_command channel; and not __fish_seen_subcommand_from $channel_commands" -a new    -d "Create a new, empty channel"
complete -c pijul -n "__fish_pijul_seen_command channel; and not __fish_seen_subcommand_from $channel_commands" -a rename -d "Rename a channel"
complete -c pijul -n "__fish_pijul_seen_command channel; and not __fish_seen_subcommand_from $channel_commands" -a switch -d "Switch to a channel. There must not be unrecorded changes in the working copy"
complete -c pijul -n "__fish_pijul_seen_command channel; and __fish_seen_subcommand_from switch" -s f -l force
complete -c pijul -n "__fish_pijul_seen_command channel; and __fish_seen_subcommand_from delete rename switch" -xa "(__fish_complete_pijul_channels)"

# # pijul clone
complete -c pijul -n __fish_pijul_needs_command -a clone -d "Clones an existing pijul repository"
complete -c pijul -n "__fish_pijul_seen_command clone" -l change     -x -d "Clone this change and its dependencies"
complete -c pijul -n "__fish_pijul_seen_command clone" -l channel    -x -d "Set the remote channel"
complete -c pijul -n "__fish_pijul_seen_command clone" -s k             -d "Do not check certificates (HTTPS remotes only, this option might be dangerous)"
complete -c pijul -n "__fish_pijul_seen_command clone" -l path       -x -d "Clone this path only"
complete -c pijul -n "__fish_pijul_seen_command clone" -l state      -x -d "Clone this state"

# # pijul credit
complete -c pijul -n __fish_pijul_needs_command -a credit -d "Shows which patch last affected each line of every file"
complete -c pijul -n "__fish_pijul_seen_command credit" -F
complete -c pijul -n "__fish_pijul_seen_command credit" -l channel    -xa "(__fish_complete_pijul_channels)" -d "Use this channel, instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command credit" -l repository -rF                                    -d "Set the repository where this command should run"

# # pijul diff
complete -c pijul -n __fish_pijul_needs_command -a diff -d "Shows difference between two channels/changes"
complete -c pijul -n "__fish_pijul_seen_command diff" -F
complete -c pijul -n "__fish_pijul_seen_command diff"      -l channel    -xa "(__fish_complete_pijul_channels)" -d "Use this channel, instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command diff"      -l json           -d "Output the diff in JSON format instead of the default change text format"
complete -c pijul -n "__fish_pijul_seen_command diff"      -l repository -rF -d "Set the repository where this command should run"
complete -c pijul -n "__fish_pijul_seen_command diff" -s s -l short          -d "Show a short version of the diff"
complete -c pijul -n "__fish_pijul_seen_command diff"      -l tag            -d "Add all the changes of this channel as dependencies (except changes implied transitively), instead of the minimal dependencies"
complete -c pijul -n "__fish_pijul_seen_command diff" -s u -l untracked      -d "Include the untracked files"

# # pijul fork
complete -c pijul -n __fish_pijul_needs_command -a fork -d "Create a new channel"
complete -c pijul -n "__fish_pijul_seen_command fork"
complete -c pijul -n "__fish_pijul_seen_command fork" -l change     -xa "(__fish_complete_pijul_changes)"  -d "Apply this change after creating the channel"
complete -c pijul -n "__fish_pijul_seen_command fork" -l channel    -xa "(__fish_complete_pijul_channels)" -d "Make the new channel from this channel instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command fork" -l repository -rF -d "Set the repository where this command should run"

# # pijul git
complete -c pijul -n __fish_pijul_needs_command -a git -d "Imports a git repository into pijul"
complete -c pijul -n "__fish_pijul_seen_command git" -F

# pijul init
complete -c pijul -n __fish_pijul_needs_command -a init -d "Initializes an empty pijul repository"
complete -c pijul -n "__fish_pijul_seen_command init" -F
complete -c pijul -n "__fish_pijul_seen_command init"      -l channel -xa "(__fish_complete_pijul_channels)" -d "Set the name of the current channel"
complete -c pijul -n "__fish_pijul_seen_command init" -s k -l kind    -xa "rust node nodejs lean"            -d "Project kind"

# pijul key
set -l key_commands generate prove
complete -c pijul -n __fish_pijul_needs_command -a key -d "Key generation and management"
complete -c pijul -n "__fish_pijul_seen_command key; and not __fish_seen_subcommand_from $key_commands" -a generate -d "Generate a new key"
complete -c pijul -n "__fish_pijul_seen_command key; and not __fish_seen_subcommand_from $key_commands" -a prove    -d "Associate a generated key with a remote identity"
complete -c pijul -n "__fish_pijul_seen_command key; and __fish_seen_subcommand_from generate" -l email -d "Email to associate with the local identity"
complete -c pijul -n "__fish_pijul_seen_command key; and __fish_seen_subcommand_from generate" -x
complete -c pijul -n "__fish_pijul_seen_command key; and __fish_seen_subcommand_from prove"    -s k     -d "Do not check certificates (HTTPS remotes only, this option might be dangerous)"
complete -c pijul -n "__fish_pijul_seen_command key; and __fish_seen_subcommand_from prove"    -xa "(__fish_complete_pijul_remotes)"

# pijul list
for x in list ls
  complete -c pijul -n __fish_pijul_needs_command -a $x -d "List files tracked by pijul"
  complete -c pijul -n "__fish_pijul_seen_command $x" -l repository -rF -d "Set the repository where this command should run"
end

# pijul log
complete -c pijul -n __fish_pijul_needs_command -a log -d "Show the entire log of changes"
complete -c pijul -n "__fish_pijul_seen_command log" -l channel       -xa "(__fish_complete_pijul_channels)" -d "Show logs for this channel instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command log" -l description       -d "Include full change description in the output"
complete -c pijul -n "__fish_pijul_seen_command log" -l hash-only         -d "Only show the change hashes"
complete -c pijul -n "__fish_pijul_seen_command log" -l limit         -r  -d "Show logs for this channel instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command log" -l offset        -r  -d "Show logs for this channel instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command log" -l output-format -xa "json default"                     -d "Output format of logs"
complete -c pijul -n "__fish_pijul_seen_command log" -l repository    -rF -d "Set the repository where this command should run"
complete -c pijul -n "__fish_pijul_seen_command log" -l state             -d "Include state identifiers in the output"

# pijul move
for x in move mv
  complete -c pijul -n __fish_pijul_needs_command -a $x -d "Moves a file in the working copy and the tree"
  complete -c pijul -n "__fish_pijul_seen_command $x" -rF
end

# pijul pull
complete -c pijul -n __fish_pijul_needs_command -a pull -d "Pulls changes from a remote upstream"
complete -c pijul -n "__fish_pijul_seen_command pull" -a "(__fish_complete_pijul_remotes)"
complete -c pijul -n "__fish_pijul_seen_command pull" -s a -l all            -d "Pull all changes"
complete -c pijul -n "__fish_pijul_seen_command pull" -s f -l force-cache    -d "Force an update of the local remote cache"
complete -c pijul -n "__fish_pijul_seen_command pull"      -l from-channel -xa "(__fish_complete_pijul_channels)" -d "Pull from this remote channel"
complete -c pijul -n "__fish_pijul_seen_command pull"      -l full           -d "Download full changes, even when not necessory"
complete -c pijul -n "__fish_pijul_seen_command pull" -s k                   -d "Do not check certificates (HTTPS remotes only, this option might be dangerous)"
complete -c pijul -n "__fish_pijul_seen_command pull"      -l path       -rF -d "Only pull to these paths"
complete -c pijul -n "__fish_pijul_seen_command pull"      -l repository -rF -d "Set the repository where this command should run"
complete -c pijul -n "__fish_pijul_seen_command pull"      -l to-channel   -xa "(__fish_complete_pijul_channels)" -d "Pull into this channel instead of the current channel"

# pijul push
complete -c pijul -n __fish_pijul_needs_command -a push -d "Pushes changes to a remote upstream"
complete -c pijul -n "__fish_pijul_seen_command push" -a "(__fish_complete_pijul_remotes)"
complete -c pijul -n "__fish_pijul_seen_command push" -s a -l all              -d "Pull all changes"
complete -c pijul -n "__fish_pijul_seen_command push" -s f -l force-cache      -d "Force an update of the local remote cache"
complete -c pijul -n "__fish_pijul_seen_command push"      -l from-channel -xa "(__fish_complete_pijul_channels)" -d "Push from this channel instead of the default channel"
complete -c pijul -n "__fish_pijul_seen_command push" -s k                     -d "Do not check certificates (HTTPS remotes only, this option might be dangerous)"
complete -c pijul -n "__fish_pijul_seen_command push"      -l path         -rF -d "Push changes only relating to these paths"
complete -c pijul -n "__fish_pijul_seen_command push"      -l repository   -rF -d "Path to the repository. Uses the current repository if the argument is omitted"
complete -c pijul -n "__fish_pijul_seen_command push"      -l to-channel   -xa "(__fish_complete_pijul_channels)" -d "Push to this remote channel instead of the remote's default channel"

# pijul record
complete -c pijul -n __fish_pijul_needs_command -a record -d "Creates a new change"
complete -c pijul -n "__fish_pijul_seen_command record" -F
complete -c pijul -n "__fish_pijul_seen_command record" -s a -l all              -d "Record all paths that have changed"
complete -c pijul -n "__fish_pijul_seen_command record"      -l amend        -xa "(__fish_complete_pijul_changes)"  -d "Amend this change instead of creating a new change"
complete -c pijul -n "__fish_pijul_seen_command record"      -l author       -x  -d "Set the author field"
complete -c pijul -n "__fish_pijul_seen_command record"      -l channel      -xa "(__fish_complete_pijul_channels)" -d "Record the change in this channel instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command record"      -l ignore-missing   -d "Ignore missing (deleted) files"
complete -c pijul -n "__fish_pijul_seen_command record" -s m -l message      -x  -d "Set the change message"
complete -c pijul -n "__fish_pijul_seen_command record"      -l repository   -rF -d "Set the repository where this command should run"
complete -c pijul -n "__fish_pijul_seen_command record"      -l timestamp    -x  -d "Set the timestamp field"
complete -c pijul -n "__fish_pijul_seen_command record"      -l working-copy -x

function __fish_complete_pijul_remote_ids
  pijul remote | string trim | string replace -r ": " "\t"
end

# pijul remote
set -l remote_commands delete
complete -c pijul -n __fish_pijul_needs_command -a remote -d "Manages remote repositories"
complete -c pijul -n "__fish_pijul_seen_command remote" -l repository -rF -d "Set the repository where this command should run"
complete -c pijul -n "__fish_pijul_seen_command remote; and not __fish_seen_subcommand_from $remote_commands" -a delete         -d "Delete a remote"
complete -c pijul -n "__fish_pijul_seen_command remote; and __fish_seen_subcommand_from delete" -xa "(__fish_complete_pijul_remote_ids)"

# pijul remove
complete -c pijul -n __fish_pijul_needs_command -a remove -d "Removes a file from the tree and pristine"
complete -c pijul -n "__fish_pijul_seen_command remove" -l repository -d "Set the repository where this command should run"

# pijul reset
complete -c pijul -n __fish_pijul_needs_command -a reset -d "Reverts the working copy to the given hash"
complete -c pijul -n "__fish_pijul_seen_command reset" -F
complete -c pijul -n "__fish_pijul_seen_command reset"      -l channel    -xa "(__fish_complete_pijul_channels)" -d "Reset the working copy to this channel, and change the current channel to this channel"
complete -c pijul -n "__fish_pijul_seen_command reset"      -l dry-run        -d "Print a single file reset to the standard output"
complete -c pijul -n "__fish_pijul_seen_command reset" -s f -l force          -d "Reset even if there are unrecorded changes"
complete -c pijul -n "__fish_pijul_seen_command reset"      -l repository -rF -d "Set the repository where this command should run"

# pijul unrecord
complete -c pijul -n __fish_pijul_needs_command -a unrecord -d "Unrecords a list of changes"
complete -c pijul -n "__fish_pijul_seen_command unrecord" -a "(__fish_complete_pijul_changes)"
complete -c pijul -n "__fish_pijul_seen_command unrecord" -l channel -xa "(__fish_complete_pijul_channels)" -d "Unrecord changes from this channel instead of the current channel"
complete -c pijul -n "__fish_pijul_seen_command unrecord" -l repository -rF -d "Set the repository where this command should run"
complete -c pijul -n "__fish_pijul_seen_command unrecord" -l reset -d "Also undo the changes in the working copy"
complete -c pijul -n "__fish_pijul_seen_command unrecord" -l show-changes -d "Show the last N changes in interactive mode"

# pijul help
complete -c pijul -n __fish_pijul_needs_command -a help -d "Print pijul help text"