Bug 1670288 Comment 7 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

So I tinkered around a little with this and came up with the following "dynamic" completion script for fish shells. It loads and executes the correct completion script based on the `mach` binary path you give it or the current tree you are in.

```fish
# This is base on the `get_state_dir` in python/mach/mach/utils.py
function __mach_get_state_dir -a source_dir
    set -l dir_basename (path basename "$source_dir")
    set -l dir_hash (string sub -l 12 (sha256 -s "$source_dir"))
    echo "$HOME/.mozbuild/srcdirs/$dir_basename-$dir_hash"
end

function __mach_find_completion_script -a executable_path
    # Prefer the directory hinted by the executable path (./mach, ../mach, etc.)
    set -l search_dir (path dirname $executable_path)
    set -l state_dir (__mach_get_state_dir $search_dir)
    if test -d "$state_dir"
        echo "$state_dir/completions/mach.fish"
        return
    end

    # Otherwise, walk upward from the current working directory
    set search_dir (pwd)
    while test "$search_dir" != /
        set state_dir (__mach_get_state_dir "$search_dir")
        if test -d "$state_dir"
            echo "$state_dir/completions/mach.fish"
            return
        end
        set search_dir (path dirname "$search_dir")
    end

    return 1
end

function __mach_dynamic_completion
    set -l command_name (commandline -opc)[1]
    set -l executable_path (realpath "$(command -v "$command_name")")

    set -l com_script (__mach_find_completion_script $executable_path); or return

    # Execute the completion script found
    fish --no-config --private -c "source $com_script; complete -C \"$(commandline)\""
end

complete -c mach -f -a "(__mach_dynamic_completion)"
```

Running `mach bootstrap` would write this completion script to a [fish completion directory](https://fishshell.com/docs/current/completions.html#where-to-put-completions) and would then trigger the hook manually once to generate the completion for the work tree.

For the hook phase I landed on `post-checkout`, it works nicely and also generates the completion if you add a new work tree (so you only have to call `mach bootstrap` once for the completion to work in every work tree). The issue is that git only supports one hook per phase, and all work trees share the same hooks. If someone already has a `post-checkout` hook in his `moz-central` checkout, we probably just want to skip writing the hook with a warning message being printed to the console. 

Besides that, I haven't tried to implement the same type of dynamic completion for bash.
So I tinkered around a little with this and came up with the following "dynamic" completion script for fish shells. It loads and executes the correct completion script based on the `mach` binary path you give it or the current tree you are in.

```fish
# This is base on the `get_state_dir` in python/mach/mach/utils.py
function __mach_get_state_dir -a source_dir
    set -l dir_basename (path basename "$source_dir")
    set -l dir_hash (string sub -l 12 (sha256 -s "$source_dir"))
    echo "$HOME/.mozbuild/srcdirs/$dir_basename-$dir_hash"
end

function __mach_find_completion_script -a executable_path
    # Prefer the directory hinted by the executable path (./mach, ../mach, etc.)
    set -l search_dir (path dirname $executable_path)
    set -l state_dir (__mach_get_state_dir $search_dir)
    if test -d "$state_dir"
        echo "$state_dir/completions/mach.fish"
        return
    end

    # Otherwise, walk upward from the current working directory
    set search_dir (pwd)
    while test "$search_dir" != /
        set state_dir (__mach_get_state_dir "$search_dir")
        if test -d "$state_dir"
            echo "$state_dir/completions/mach.fish"
            return
        end
        set search_dir (path dirname "$search_dir")
    end

    return 1
end

function __mach_dynamic_completion
    set -l command_name (commandline -opc)[1]
    set -l executable_path (realpath "$(command -v "$command_name")")

    set -l com_script (__mach_find_completion_script $executable_path); or return

    # Execute the completion script found
    fish --no-config --private -c "source $com_script; complete -C \"$(commandline)\""
end

complete -c mach -f -a "(__mach_dynamic_completion)"
```

Running `mach bootstrap` would write this completion script to a [fish completion directory](https://fishshell.com/docs/current/completions.html#where-to-put-completions) and would then trigger the hook manually once to generate the completion for the work tree.

For the hook phase I landed on `post-checkout`, it works nicely and also generates the completion if you add a new work tree (so you only have to call `mach bootstrap` once for the completion to work in every work tree). The issue is that git only supports one hook per phase, and all work trees share the same hooks. If someone already has a `post-checkout` hook in their `moz-central` checkout, we probably just want to skip writing the hook with a warning message being printed to the console. 

Besides that, I haven't tried to implement the same type of dynamic completion for bash.

Back to Bug 1670288 Comment 7