Code Monkey home page Code Monkey logo

completely's Introduction

Completely - Bash Completions Generator

Gem Version Build Status Maintainability


Completely is a command line utility and a Ruby library that lets you generate bash completion scripts from simple YAML configuration.

This tool is for you if:

  1. You develop your own command line tools.
  2. Your life feels empty without bash completions.
  3. Bash completion scripts seem overly complex to you.

Note that if you are building bash command line scripts with bashly, then this functionality is already integrated with it.


Install

$ gem install completely

or with homebrew:

$ brew install brew-gem
$ brew gem install completely

or with Docker:

$ alias completely='docker run --rm -it --user $(id -u):$(id -g) --volume "$PWD:/app" dannyben/completely'

Using the completely command line

The completely command line works with a simple YAML configuration file as input, and generates a bash completions script as output.

The configuration file is built of blocks that look like this:

pattern:
- --argument
- --param
- command

Each pattern contains an array of words (or functions) that will be suggested for the auto complete process.

You can save a sample YAML file by running:

$ completely init

This will generate a file named completely.yaml with this content:

mygit:
- --help
- --version
- status
- init
- commit

mygit status:
- --help
- --verbose
- --branch
- $(git branch 2>/dev/null)

mygit init:
- --bare
- <directory>

mygit commit:
- <file>
- --help
- --message
- --all
- -a
- --quiet
- -q

Each pattern in this configuration file will be checked against the user's input, and if the input starts with a matching pattern, the list that follows it will be suggested as completions.

Note that the suggested completions will not show flags (string that start with a hyphen -) unless the input ends with a hyphen.

To generate the bash script, simply run:

$ completely generate

# or, to just preview it without saving:
$ completely preview

For more options (like setting input/output path), run:

$ completely --help

Suggesting files, directories and other bash built-ins

In addition to specifying a simple array of completion words, you may use the special syntax <..> to suggest more advanced functions.

pattern:
- <file>
- <directory>

These suggestions will add the list of files and directories (when <file> is used) or just directories (when <directory> is used) to the list of suggestions.

You may use any of the below keywords to add additional suggestions:

Keyword Meaning
<alias> Alias names
<arrayvar> Array variable names
<binding> Readline key binding names
<builtin> Names of shell builtin commands
<command> Command names
<directory> Directory names
<disabled> Names of disabled shell builtins
<enabled> Names of enabled shell builtins
<export> Names of exported shell variables
<file> File names
<function> Names of shell functions
<group> Group names
<helptopic> Help topics as accepted by the help builtin
<hostname> Hostnames, as taken from the file specified by the HOSTFILE shell variable
<job> Job names
<keyword> Shell reserved words
<running> Names of running jobs
<service> Service names
<signal> Signal names
<stopped> Names of stopped jobs
<user> User names
<variable> Names of all shell variables

For those interested in the technical details, any word between <...> will simply be added using the compgen -A action function, so you can in fact use any of its supported arguments.

Suggesting custom dynamic suggestions

You can also use any command that outputs a whitespace-delimited list as a suggestions list, by wrapping it in $(..). For example, in order to add git branches to your suggestions, use the following:

mygit:
- $(git branch 2>/dev/null)

The 2> /dev/null is used so that if the command is executed in a directory without a git repository, it will still behave as expected.

Suggesting flag arguments

Adding a * wildcard in the middle of a pattern can be useful for suggesting arguments for flags. For example:

mygit checkout:
- --branch
- -b

mygit checkout*--branch:
- $(git branch 2>/dev/null)

mygit checkout*-b:
- $(git branch 2>/dev/null)

The above will suggest git branches for commands that end with -b or --branch. To avoid code duplication, you may use YAML aliases, so the above can also be written like this:

mygit checkout:
- --branch
- -b

mygit checkout*--branch: &branches
- $(git branch 2>/dev/null)

mygit checkout*-b: *branches

Using the generated completion scripts

In order to enable the completions, simply source the generated script:

$ source completely.bash

If you are satisfied with the result, and wish to copy the script to your bash completions directory, simply run:

$ completely install

Alternatively, you can copy the script manually to one of these directories (whichever exists):

  • /usr/share/bash-completion/completions
  • /usr/local/etc/bash_completion.d
  • ~/.local/share/bash-completion/completions

Testing and debugging completion scripts

You can use the built in completions script tester by running completely test.

This command lets you test completions for your completions script.

In addition, you can set the COMPLETELY_DEBUG environment variable to any value in order to generate scripts with some additional debugging functionality. Run completely generate --help for additional information.

Using from within Ruby code

require 'completely'

# Load from file
completions = Completely::Completions.load "input.yaml"

# Or, from a hash
input = {
  "mygit" => %w[--help --version status init commit],
  "mygit status" => %w[--help --verbose --branch]
}
completions = Completely::Completions.new input

# Generate the script
puts completions.script

# Or, generate a function that echos the script
puts completions.wrapper_function
puts completions.wrapper_function "custom_function_name"

# Or, test the completions with the Tester object
p completions.tester.test "mygit status "

Completions in ZSH

If you are using Oh-My-Zsh, bash completions should already be enabled, otherwise, you should enable completion by adding this to your ~/.zshrc (if is it not already there):

# Load completion functions
autoload -Uz +X compinit && compinit
autoload -Uz +X bashcompinit && bashcompinit

Contributing / Support

If you experience any issue, have a question or a suggestion, or if you wish to contribute, feel free to open an issue.


completely's People

Contributors

dannyben avatar kronn avatar postmodern avatar truncateddinosour avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

completely's Issues

Update the Zsh instructions on how to correctly use the Bash completions

After installing my completion files into /usr/local/etc/bash_completion.d/ they are automatically loaded by Bash, but not by Zsh. Even after adding the suggested Zsh configuration to ~/.zshrc the bash completions are not automatically loaded by Zsh. I think the Zsh instructions need to mention this, or that one must install the Bash completion files into /usr/local/share/zsh/site-functions. or that ~/.zshrc should explicitly source the bash completions from wherever they were installed to.

Completion for command --option=value

Hi,

Thanks for this nice project.

I try to have completion for my_command --option=value.

I have tested this:

my_command:
- do-this
- do-that
- --output-format=

my_command --output-format:
- text
- csv
- json
- xml

my_command do-this:
- ''

my_command do-that:
- ''

my_command --<TAB><TAB> put a space after =: my_command --output-format= , and there is no more completion for do-this and do-that.

I also try this :

my_command:
- do-this
- do-that
- --output-format=text
- --output-format=csv
- --output-format=json
- --output-format=xml

my_command do-this:
- ''

my_command do-that:
- ''

There is no space, but the completion stop after --output-format=.

Is it possible do have completion for command --option=value?

handle positional arguments

I have some shell scripts that have positional arguments. It does not look like completely support this?

Could look like:

command [--anoption] [--exclude_file <file>] <path> <group> [extragroup]
command:
- --anoption
- --exclude_file
command*--exclude_file:
- <file>
command*1:
- <file>
- <dir>
command*2:
- <group>
command?3:
- <group>

Support generating Zsh specific completion files

Hello, I would like to write a command which automatically installs the completion files without any additional user interaction or configuration. Currently, I would have to request the user to enable bashcompinit in the users ~/.zshrc, or I would have to prepend autoload -Uz +X compinit && compinit and autoload -Uz +X bashcompinit && bashcompinit to each completion file, so that the completion files can be directly installed into Zsh's site-functions directory.

If it would be possible to generate a separate Bash and Zsh completion files, it would make it easier to automatically install them based on the SHELL environment variable.

Question: how to define completion rule for a `--option FILE` option?

Hello, how can I define a completion rule for an option which accepts a file. The examples show that one can define option flags under a command, and <file> keywords under a command, but can I do --option <file>?

Also you should enable GitHub Discussions so people can submit questions there, instead of cluttering up the Issues.

Question: is it possible to not match unknown patterns?

I am attempting to create completions for a program that can run plugins. The plugins in these cases are external binaries for which I do not have information about their arguments. Is there a way to define not to suggest any completion in case of unknown patterns?

A small example would be

my_cmd:
- plugins
- $(my_cmd plugins list)

my_cmd plugin:
- list

In the case above, I would like for completion to work for my_cmd plugins <TAB> and show me the list subcommand. But when I type my_cmd my_plugin where my_plugin is an external binary, nothing shows up. Is that possible?

Option to only complete flags when `-` has been typed

First of all, thank you for your excellent projects, bashly and completely. They are fantastic and certainly made creating Bash tools more bearable.

Seeing the improvements made to flag autocompletion from DannyBen/bashly#224, I wonder if it would be possible, maybe as an opt-in setting, to make the completion only output flags when the cursor has stopped at -, and output no flags otherwise.

I think this behaviour is pretty common and used in many tools' completions. In essence:

# complete flags:
mytool -<TAB>
mytool --<TAB>
# complete other stuff, i.e. files, folders, etc.
mytool <TAB>

What do you think?

On a separate note, normally shellcheck complains about read without -r, I'm unsure if it should be included here?
See https://www.shellcheck.net/wiki/SC2162

Should we add `completely install` command to install completions?

We can port this logic from bash:

# Figure out if we need sudo or not
sudo=''
if [[ $EUID -ne 0 ]]; then
  sudo='sudo'
fi

# Install completions
if [[ -d "/usr/share/bash-completion/completions" ]]; then
  compdir="/usr/share/bash-completion/completions"
elif [[ -d "/usr/local/etc/bash_completion.d" ]]; then
  compdir="/usr/local/etc/bash_completion.d"
else
  compdir=''
fi

if [[ -n $compdir ]]; then
  echo "=== Installing autocompletions to $compdir"
  echo "eval \"\$(rush completions)\"" | $sudo tee "${compdir}/rush" > /dev/null
else
  echo "=== Completion script was not installed"
  echo "    To install it manually add this to your startup script:"
  echo "    eval \"\$(rush completions)\""
fi

Docker support

Hi,

Does this project plans to a have a docker image ready to be used such as bashly?
Since Ubuntu 18.04 does not support ruby>2.7 via packager manager, I currently cannot use such project out-of-the box as compared to bashly.

Thanks.

Wildcards after the first word are not working

Discovered by @rience in DannyBen/bashly#292 (reply in thread)


Using the following completely.yaml:

cli:
- "--env"

cli*--env:
- prod
- dev

and running:

$ completely preview

prints a warning:

WARNING:
Your configuration is invalid.
All patterns must start with the same word

and generates an invalid file containing this:

  case "$compline" in
    *)
      while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_cli_completions_filter "prod dev")" -- "$cur" )
      ;;

    *)
      while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_cli_completions_filter "--env")" -- "$cur" )
      ;;

  esac

Running `completely test` should also show a warning when the file is invalid

Using the following completely.yaml:

---
one:
- "--debug"

two:
- "--help"

and running:

$ completely preview

prints a warning (as expected):

WARNING:
Your configuration is invalid.
All patterns must start with the same word

The same warning should be displayed when running:

$ completely test one

but it isn't.

Could we use another program completion ?

After a bit of searching, I found that you could use complete -F to use another command completion and didn't find example of that in Completely.
Do you support it ? If not is it something you'd be considering ?
Thanks for your great work.

Allow saving the tester script

Add --keep flag to completely test which will copy the test script used to the current directory.

This can be helpful for debugging, development, or if someone wants to use it to test other things.

completion breaks on spaces in paths

completion functions generated using <file> and <directory> syntax dont seem to handle paths containing whitespace correctly. since compgen output is newline-delimited i think this could be fixed by replacing COMPREPLY=( $( compgen ... ) ) with readarray -t COMPREPLY < <( compgen ... ). or am i doing something wrong?

thanks for this library and for bashly! theyre both lovely

ZSH Autocompletions only work on first new terminal

Using bashly and following your instructions I have the following on my .zshrc

# Load completion functions
autoload -Uz +X compinit && compinit
autoload -Uz +X bashcompinit && bashcompinit

eval "$(my_script completions)"

Afterwards if open a new terminal to source .zshrc everything works as expected. However in all other new terminals, it doesn't work again.

Other people at my company are using the same script and zsh, and I've tried many of the solutions posted online but so far they haven't worked for me, so I know that this is something unique to my situation, but I've completely (pun not intended) ran out of options, so perhaps you can assist me here.

QUESTION: complete a term with a colon / :

This project makes me almost completely happy. I want to write a completion for rspec, which is mostly painless. After being finished with my (opinionated) completion, I wanted to also complete the tags, which are tag:value-pairs. I generate the list with a small helper that returns a list that roughly looks like this:

js:false
js:true
sphinx:true
type:controller
type:feature
~js:false
~js:true
~sphinx:true
~type:controller
~type:feature

(naturally, there's more, but this shows the problem well enough)

The tag sphinx:true is easy, since it has the : inside the word. It gets completed in one <TAB>. The negated tags with the ~-prefix are also unproblematic.

For the others, the difference comes after the :. So it is printed but does not allow further completion. I can go back, escape the :, add another character and complete from there.

Let's just say that the ergonomics differ slightly between
rsp<TAB>--tag sph<TAB><ENTER> and
rsp<TAB>--tag ty<TAB><BACKSPACE>\:c<TAB><ENTER>

And yes, the last <TAB> completes type\:c to type:controller, removing my escape-hack and leaving me with the intended command. However, trying to complete type:c trigger the generic fallback of file-completion for c.

I realize that I do not have a completion-issue, but a shell-escape-issue (as so often when doing things in bash). Do you know of a solution for this? I have the feeling that the _completions_filter-function might be a place for a fix. How this potential fix is the propagated into the config-yaml is as unknown as the fix itself.

This is all I know now. Can you help or provide pointers for a PR I can create?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.