jqlang / jq

Command-line JSON processor
https://jqlang.github.io/jq/
Other
29.98k stars 1.55k forks source link

jq Shell Autocomplete #1417

Open jeffquinn-nuna opened 7 years ago

jeffquinn-nuna commented 7 years ago

Hello,

First of all big fan of jq, one of my all time favorite tools.

One question: has anyone ever tried making an autocomplete module? I was thinking of something similar to https://github.com/git/git/blob/master/contrib/completion/git-completion.bash

My idea was it could work by just throwing the result of jq '. | keys' on the file under examination into the autocomplete index. Figuring out which file is under examination might be tough, could default to everything in the current working directory maybe.

Let me know what you think,

Jeff

wtlangford commented 7 years ago

I haven't heard of any such thing, but that sounds pretty interesting!

Writing bash/zsh/*sh completion scripts is not very high on my list of "things that are fun to do", though. 😉

That said, if you want to make a PR, we'd certainly consider it!

Some caveats that spring to mind:

On Sat, May 20, 2017, 07:49 Jeff Quinn notifications@github.com wrote:

Hello,

First of all be fan of jq, one of my all time favorite tools.

One question: has anyone ever tried making an autocomplete module? I was thinking of something similar to https://github.com/git/git/blob/master/contrib/completion/git-completion.bash

My idea was it could work by just throwing the result of jq '. | keys' on the file under examination into the autocomplete index. Figuring out which file is under examination might be tough, could default to everything in the current working directory maybe.

Let me know what you think,

Jeff

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/stedolan/jq/issues/1417, or mute the thread https://github.com/notifications/unsubscribe-auth/ADQ4Vx-ZQJFi-pH93awL1Trbn75PrDVSks5r7hxsgaJpZM4NhF2x .

jeffquinn-nuna commented 7 years ago

Thanks for the response :)

Shell scripts are also not on my fun list either. I was surprised to see how insanely complicated the example I linked for git autocomplete is.

If it sounds useful to you I might take another look next time I have this problem. Maybe there is a library or framework example out there for new shell autocomplete scripts..

hoshsadiq commented 6 years ago

Just came here to figure out if there's an autocompletion script. I will try and write one at some point. However, some thoughts on OP.

IMO we shouldn't bother with jq '. | keys', at least not in the beginning. The args would be priority to include in autocompletion, and then later maybe include the keys of the inputs.

perlpunk commented 5 years ago

Hi,

I just added jq to my completion collection (which is still pretty new). You can find completions for bash and zsh:

It only completes flags and options. I think completing the filter is too complicated.

The scripts might look overcomplicated, but that is because they are generated by a tool that works on generic script specifications (with subcommands and dynamic completions calling other commands). Here's the specification: https://github.com/perlpunk/shell-completions/blob/master/specs/jq.yaml

Edit: also, completion for --arg and argjson will not work correctly because my tool can only recognize options with one argument, but they get two arguments. I plan to add support for that but that's low priority.

jbriales commented 5 years ago

Also came here looking for this. Just as a very reduced toy example I created this gist. Now you can do autocompletion on keys like this: jq toy .<TAB> -> prints autocompletion options: .bar .foo .quz jq toy .f<TAB> -> jq toy .foo, ENTER -> print 1 See the gist for details and more comments.

a-b commented 10 months ago

Any updates on this one? IMHO basic filter completion > nothing. Curious if having jq special flag to generate some primitives for the autocomplete function could help with this challenge.

0xdevalias commented 8 months ago

A few resources I found when briefly looking into automated ways to do this:

Details - https://github.com/openautocomplete/openautocomplete - > OpenAutoComplete -- CLI autocomplete specification - https://github.com/openautocomplete/completions - > OpenAutoComplete definitions collection - https://news.ycombinator.com/item?id=23254432 - https://unix.stackexchange.com/questions/417054/automatically-generate-zsh-bash-completion-files - > To complete short and long options and file names, make sure that the program generates a usage description with `--help` in the same format as GNU tools. Then set it up for completion with: > > - `complete -F _longopt myprogram` in bash > - `compdef _gnu_generic myprogram` in zsh > > If you want something more powerful, define bash completions and use zsh's bash compatibility mode. Users must call [`bashcompinit`](http://zsh.sourceforge.net/Doc/Release/Completion-System.html#index-bashcompinit) in their `.zshrc`, then they can call `complete -F _myprogram_bash_complete myprogram` in zsh as well as bash. Zsh only emulates a subset of bash, so test your completion function to ensure that it doesn't require features that zsh doesn't emulate. - https://zsh.sourceforge.io/Doc/Release/Completion-System.html - > Note also the `_gnu_generic` function described below, which can be used to complete options for commands that understand the ‘--help’ option. - > `_arguments`: This function can be used to give a complete specification for completion for a command whose arguments follow standard UNIX option and argument conventions. - > `_gnu_generic`: This function is a simple wrapper around the _arguments function described above. It can be used to determine automatically the long options understood by commands that produce a list when passed the option ‘--help’. It is intended to be used as a top-level completion function in its own right. For example, to enable option completion for the commands foo and bar, use `compdef _gnu_generic foo bar` after the call to compinit > > The completion system as supplied is conservative in its use of this function, since it is important to be sure the command understands the option ‘--help’. - https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html - https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html

I'm not sure what aspect of my zsh setup and/or dotfiles does it, but I seem to already get standard jq completions?

⇒ jq -<tab>
--arg                    -- pre-set a variable to a string
--argjson                -- pre-set a variable to an object
--args                   -- remaining arguments are string arguments, not files
--ascii-output       -a  -- restrict output to ASCII
--color-output       -C  -- output in color
--compact-output     -c  -- don't pretty-print
# ..snip..
annamedv commented 5 months ago

Looks like creating JSON field autocompletion is also doable.

For example, in fx json tool autocomplete works amazingly well:

fx autocomplete

I guess this is due to fx's file argument can be first (or last), and in jq file argument is always last.

wader commented 5 months ago

@annamedv i don't know much about shell completion but i wonder if the way fq does completion in it's REPL might be possible somehow? example using the internal _complete function that the REPL uses:

# complete keys, also support evaluating
$ fq -n '[{a:{bcd:123}}] | _complete(".a.bbb=456 | .a.b")'
{
  "names": [
    "bbb",
    "bcd"
  ],
  "prefix": "b"
}

# complete function names
$ fq -n '[null] | _complete("fromd")'
{
  "names": [
    "fromdate",
    "fromdateiso8601"
  ],
  "prefix": "fromd"
}

It works by doing some AST inspection and rewrite tricks. Simplified it first figure out if the query ends with a function or a key, if function use some scope magic, if a key append and eval ... | keys | map(select(startswith(...))) | sort | unique but that would require that something can do the query parsing, maybe some kind of helper program or use code from https://github.com/wader/jqjq?

Maybe a simpler alternative is to only support basic indexing and implement that directly in jq somehow?