Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: completions command #1157

Merged
merged 1 commit into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmd/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ func run() error {
return nil
}

if flags.Completion != "" {
script, err := task.Completion(flags.Completion)
if err != nil {
return err
}
fmt.Println(script)
return nil
}

if flags.Global {
home, err := os.UserHomeDir()
if err != nil {
Expand Down
34 changes: 34 additions & 0 deletions completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package task

import (
_ "embed"
"fmt"
)

//go:embed completion/bash/task.bash

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to define them in the methods? I mean does go:embed requires them to be defined in package scope.

I mean this constants will be defined in RAM even if you don't need completion, no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go embeds must be defined at a package level as described in the docs.

It can only be used with variables at package scope, not with local variables

However this does not necessarily mean that the bytes are loaded into memory immediately. Even if they were to be loaded immediately, I'm not really worried about a few KB tbh.

var completionBash string

//go:embed completion/fish/task.fish
var completionFish string

//go:embed completion/ps/task.ps1
var completionPowershell string

//go:embed completion/zsh/_task
var completionZsh string

func Completion(completion string) (string, error) {
// Get the file extension for the selected shell
switch completion {
case "bash":
return completionBash, nil
case "fish":
return completionFish, nil
case "powershell":
return completionPowershell, nil
case "zsh":
return completionZsh, nil
default:
return "", fmt.Errorf("unknown shell: %s", completion)
}
}
2 changes: 2 additions & 0 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ var (
Version bool
Help bool
Init bool
Completion string
List bool
ListAll bool
ListJson bool
Expand Down Expand Up @@ -80,6 +81,7 @@ func init() {
pflag.BoolVar(&Version, "version", false, "Show Task version.")
pflag.BoolVarP(&Help, "help", "h", false, "Shows Task usage.")
pflag.BoolVarP(&Init, "init", "i", false, "Creates a new Taskfile.yml in the current folder.")
pflag.StringVar(&Completion, "completion", "", "Generates shell completion script.")
pflag.BoolVarP(&List, "list", "l", false, "Lists tasks with description of current Taskfile.")
pflag.BoolVarP(&ListAll, "list-all", "a", false, "Lists tasks with or without a description.")
pflag.BoolVarP(&ListJson, "json", "j", false, "Formats task list as JSON.")
Expand Down
25 changes: 25 additions & 0 deletions website/docs/deprecations/completion_scripts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
slug: /deprecations/completion-scripts/
---

# Completion Scripts

:::warning

This deprecation breaks the following functionality:

- Any direct references to the completion scripts in the Task git repository

:::

Direct use of the completion scripts in the `completion/*` directory of the
[github.com/go-task/task][task] Git repository is deprecated. Any shell
configuration that directly refers to these scripts will potentially break in
the future as the scripts may be moved or deleted entirely. Any configuration
should be updated to use the [new method for generating shell
completions][completions] instead.

{/* prettier-ignore-start */}
[completions]: ../installation.mdx#setup-completions
[task]: https://github.com/go-task/task
{/* prettier-ignore-end */}
88 changes: 51 additions & 37 deletions website/docs/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ slug: /installation/
sidebar_position: 2
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Installation

Task offers many installation methods. Check out the available methods below.
Expand Down Expand Up @@ -247,65 +250,76 @@ released binary.

## Setup completions

Download the autocompletion file corresponding to your shell.

[All completions are available on the Task repository](https://github.com/go-task/task/tree/main/completion).
Some installation methods will automatically install completions too, but if
this isn't working for you or your chosen method doesn't include them, you can
run `task --completion <shell>` to output a completion script for any supported
shell. There are a couple of ways these completions can be added to your shell
config:

### Bash
### Option 1. Load the completions in your shell's startup config (Recommended)

First, ensure that you installed bash-completion using your package manager.
This method loads the completion script from the currently installed version of
task every time you create a new shell. This ensures that your completions are
always up-to-date.

Make the completion file executable:
<Tabs values={[ {label: 'bash', value: '1'}, {label: 'zsh', value: '2'},
{label: 'fish', value: '3'},
{label: 'powershell', value: '4'}
]}>

```shell
chmod +x path/to/task.bash
<TabItem value="1">
```shell title="~/.bashrc"
eval "$(task --completion bash)"
```
</TabItem>

After, add this to your `~/.bash_profile`:

```shell
source path/to/task.bash
<TabItem value="2">
```shell title="~/.zshrc"
eval "$(task --completion zsh)"
```
</TabItem>

### ZSH

Put the `_task` file somewhere in your `$FPATH`:

```shell
mv path/to/_task /usr/local/share/zsh/site-functions/_task
<TabItem value="3">
```shell title="~/.config/fish/config.fish"
task --completion fish | source
```
</TabItem>

Ensure that the following is present in your `~/.zshrc`:

```shell
autoload -U compinit
compinit -i
<TabItem value="4">
```powershell title="$PROFILE\Microsoft.PowerShell_profile.ps1"
Invoke-Expression (&task --completion powershell)
```
</TabItem></Tabs>

ZSH version 5.7 or later is recommended.
### Option 2. Copy the script to your shell's completions directory

### Fish
This method requires you to manually update the completions whenever Task is
updated. However, it is useful if you want to modify the completions yourself.

Move the `task.fish` completion script:
<Tabs
values={[
{label: 'bash', value: '1'},
{label: 'zsh', value: '2'},
{label: 'fish', value: '3'}
]}>

<TabItem value="1">
```shell
mv path/to/task.fish ~/.config/fish/completions/task.fish
task --completion bash > /etc/bash_completion.d/task
```
</TabItem>

### PowerShell

Open your profile script with:

```powershell
mkdir -Path (Split-Path -Parent $profile) -ErrorAction SilentlyContinue
notepad $profile
<TabItem value="2">
```shell
task --completion zsh > /usr/local/share/zsh/site-functions/_task

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it has to be global ?

Fish example is user based

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK (Please correct me if I'm wrong), there is no standard location for completion files within a user's $HOME directory in ZSH. The user is able to add paths to their $FPATH and then place their completions in that directory, but I figure that anyone doing this already knows what to do anyway.

I have no knowledge of Bash as I haven't used it in years, but I imagine the situation is similar.

The vast majority of users will want to eval/source the script in their dotfiles instead which is why I have marked the first method as "recommended". I actually considered not adding the second method at all.

```
</TabItem>

Add the line and save the file:

<TabItem value="3">
```shell
Invoke-Expression -Command path/to/task.ps1
task --completion fish > ~/.config/fish/completions/task.fish
```
</TabItem></Tabs>

{/* prettier-ignore-start */}
[go]: https://golang.org/
Expand Down
Loading