Skip to content

Commit

Permalink
feat: Add literal command completion type
Browse files Browse the repository at this point in the history
  • Loading branch information
juanibiapina committed Jun 20, 2024
1 parent 42ee029 commit 0ada641
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 5 deletions.
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,22 @@ fi

To enable completions for positional arguments in the `Usage` comment, add an
`Options:` comment with a list of arguments. An option must have the format:
`name (completion_type): description`. Completion type is optional. Currently,
the only supported completion type is `script`, which allows for dynamic
completions like the following example:
`name (completion_type): description`. Completion type is optional.
The following completion types are supported:

- ``command``: Runs a command to generate completions. The command should print
completions to stdout:

```sh
# Usage: {cmd} <file>
# Options:
# file (`ls -1`): File or directory

# script logic
# ...
```

- `script`: allows for more complex, dynamic completions:

```sh
# Usage: {cmd} <name>
Expand All @@ -284,7 +297,7 @@ if [[ "$_HAT_COMPLETE" == "true" ]]; then
echo "Alice"
echo "Bob"
echo "Charlie"
# note that you can run any command here to generate completions
# note that you can have any logic here to generate completions
fi

# make sure to exit when generating completions to prevent the script from running
Expand Down
9 changes: 9 additions & 0 deletions integration/completions.bats
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ comp2"
comp4"
}

@test "completions: literal command: invokes command for completions" {
fixture "completions"

run main --completions literal

assert_success
assert_output "itworks"
}

@test "completions: lists nothing if command provides no completions" {
fixture "completions"

Expand Down
7 changes: 7 additions & 0 deletions integration/fixtures/completions/libexec/literal
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
#
# Usage: {cmd} <option>
# Options:
# option (`echo itworks`): Description of option

exit 202
11 changes: 11 additions & 0 deletions src/commands/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ impl<'a> Command for FileCommand<'a> {
None => Err(Error::SubCommandInterrupted),
};
},
Some(usage::CompletionType::LiteralCommand(cmd)) => {
let mut command = process::Command::new("/bin/sh");
command.arg("-c").arg(&cmd);

let status = command.status().unwrap();

return match status.code() {
Some(code) => Ok(code),
None => Err(Error::SubCommandInterrupted),
};
},
None => {
// do nothing
},
Expand Down
4 changes: 3 additions & 1 deletion src/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct UsageLang {
#[derive(Debug, PartialEq, Clone)]
pub enum CompletionType {
Script,
LiteralCommand(String),
}

#[derive(Debug, PartialEq)]
Expand All @@ -50,8 +51,9 @@ fn option_parser() -> impl Parser<char, OptionSpec, Error = Simple<char>> {
.collect();

let completion_type_script = just("script").map(|_| CompletionType::Script);
let completion_type_literal_command = just('`').ignore_then(take_until(just('`')).padded()).map(|(s, _)| CompletionType::LiteralCommand(s.into_iter().collect()));

let completion_type = completion_type_script;
let completion_type = completion_type_script.or(completion_type_literal_command);

let description = take_until(end()).padded().map(|(s, _)| s.into_iter().collect());

Expand Down

0 comments on commit 0ada641

Please sign in to comment.