Giter VIP home page Giter VIP logo

cod's Introduction

Cod is a completion daemon for bash, fish, and zsh.

It detects usage of --help commands, parses their output, and generates auto-completions for your shell.

https://asciinema.org/a/h0SrrNvZVcqoSM4DNyEUrGtQh

Install

You can either download or build the cod binary for your OS and put it into your $PATH.

After that, you will need to edit your init script (e.g. ~/.config/fish/config.fish, ~/.zshrc, ~/.bashrc) and add a few lines for the daemon to work correctly.

Bash

Add the following to your ~/.bashrc

source <(cod init $$ bash)

Zsh

Make sure completion system is initialized.

Add the following to your ~/.zshrc

source <(cod init $$ zsh)

Or, you can use a plugin manager like zinit:

zinit wait lucid for \
  dim-an/cod

Initializing zsh completion system

cod requires initialized completion system. In many cases it is already the case (e.g. if you are using oh-my-zsh or similar framework).

You can check whether your completion system is already initilized by using type compdef command:

# Completion system IS initialized
$ type compdef
compdef is a shell function from /usr/share/zsh/functions/Completion/compinit

# Completion system IS NOT initialized
$ type compdef
compdef not found

If you found that you need to initialize completion system you can do this by:

  • calling compinit function in your .zshrc before initializing cod itself, or
  • executing compinstall command from your shell, it will modify .zshrc file for you.

Also check zsh documentation.

Fish

Add the following to ~/.config/fish/config.fish

cod init $fish_pid fish | source

Fig

As an alternative, you can also install cod with Fig in bash, zsh, or fish with just one click.

https://fig.io/plugins/other/cod_dim-an

Supported shells and operating systems

  • zsh cod is known to work with latest version of zsh (tested: v5.5.1 and 5.7.1) on macOS and Linux.

  • bash cod also works with with latest version of bash (tested: 4.4.20 and v5.0.11) on Linux.

    Note that default bash that is bundled with macOS is too old and cod doesn't support it.

  • fish cod works with latest version of fish (tested: v3.1.2) on Linux (I didn't have a chance to test it on macOS).

Building cod

It is recommended that you have at least Go v1.19 installed on your machine

git clone https://github.com/dim-an/cod.git
cd cod
go build

or

go get -u github.com/dim-an/cod

Overview

Cod checks each command you run in the shell. When cod detects usage of --help flag it asks if you want it to learn this command. If you choose to allow cod to learn this command cod will run command itself parse the output and generate completions based on the --help output.

How cod detects help commands

Cod performs following checks to decide if command is help invocation:

  1. checks if the --help flag is used
  2. checks that command is simple i.e. doesn't contain any pipes, file descriptor redirections, and other shell magic
  3. checks that command exit code is 0.

If cod cannot automatically detect that your command is help invocation you can use learn subcommand to learn this command anyway.

How cod runs help commands

Cod always uses absolute paths to run programs. (So it finds the binary in $PATH or resolves relative path if required). Arguments other than the binary path are left unchanged.

The current shell environment and current working directory will be used.

If the program is successfully executed, cod will store: - the absolute path to binary - any used arguments - the working directory - environment variables This info will be used to update command if required (check: cod help update).

How cod parses help output

cod has generic parser that works with most help pages and recognizes flags (starting with -), while not recognizing subcommands.

It also has a special parser tuned for the python argparse library that recognizes flags and subcommands.

Configuration

Cod will search for the default config file $XDG_CONFIG_HOME/cod/config.toml.

The config file allows you to specify rules to either ignore or trust specified binaries

cod example-config prints an example configuration to stdout.

cod example-config --create writes an example config to the default directory of said config file ($XDG_CONFIG_HOME/cod/config.toml)

Data directories

cod uses $XDG_DATA_HOME/cod (default: ~/.local/share/cod) to store all generated data files.

cod's People

Contributors

brendanfalk avatar dim-an avatar iloveitaly avatar kidonng avatar stillru avatar supersandro2000 avatar thebearodactyl 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cod's Issues

cod doesn't parse help of nxserver correctly

This is a very cool idea. I have been looking for something just like this, I will be trying it out much more. I mainly wanted to use it for a remote desktop application called NoMachine, to manage it you use nxserver..., I have provided the --help results from the command if you'd like, its a free to use program but does have a licensing model that we use.
nxserver_help.txt

Let me apologize now, I have dyslexia so if it doesn't make sense, you may either ask me or skip over it, no worries on my end, I am just excited about this project and wanted to provide my two cents. One of the reasons I love things like these, is that short list are a lot easier for me then piles of text.

zsh
╰─➤ /usr/NX/bin/nxserver --
--address --extended --interval --per-user --trusted
--administrator --forward-connection --mask --priority --virtual
--comment --gid --minsize --screensharing
--compress --group --node --serverlist
--destination --guest --nodegroup --system
--disable --interface --nohome --timeinterval

The commands I use is nxserver --list and nxserver --history, nxserver --terminate sessionid or username... They can be used like that, or I can throw in a username or session ID.

Some Ideas for the above

  • As you can see these are not listed above. These look like sub switches to primary commands.

  • Regex --help searches. nxserver --help --regex "\n\n^--([a-z]+)(?=\s([|<)+(\w)+(]|>)+...........)\n\n"
    I'd have to run multiple regex's through it, that's a basic guess at some regex, more just to give an idea.

you could probably sed the file and make it a language that could be parsed.

  • When I type something like nxserver --li<tab_until it is selected if its not the switch selected><space or enter or shortcut key to trigger a completion scrape in the background if needed for the usernames and session ID based on a command(nxserver --list | awk '{ print $1 }') based on the previous switch --list> now be able to tab complete that?

What formatting is it looking for? Maybe I can force feed it until the project is a little further along.

Thank you so much for your time.

Allow wildcard in executable names

I want to ignore all nix commands which have the style nix, nix-build, nix-shell, etc. This is currently not possible cause wildcard can only ignore whole directories.

cod should emit standard completion scripts

It would be useful to have cod be able to generate either bash or zsh completion scripts, so that they can be distributed with a project instead of suggesting that users use cod.

cod should be able to learn man-pages

While the output of --help is usually instructive, it is less-well-formatted than most man pages.

It might be useful to have a mode where cod can learn from man pages, instead of or in-addition-to the --help output.

cod does not learn that flags belong to subcommands

The pwntools project uses a single entry point, pwn, for all of its subcommands.

COD correctly learns the subcommands, but then when learning the flags that belong to a specific subcommand, elevates them to the top-level command.

Subcommands are learned:

$ pwn --help
usage: pwn [-h]
           {asm,checksec,constgrep,cyclic,debug,disasm,disablenx,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,template,unhex,update}
...
┌──> /Users/zachriggle/.pyenv/shims/pwn --help
└─── cod: learn this command? [yn?] > y
cod: learned completions: "asm" "checksec" "constgrep" and 17 more
$ pwn <tab>
--help      asm         constgrep   debug       disasm      elfpatch    hex         pwnstrip    shellcraft  unhex
-h          checksec    cyclic      disablenx   elfdiff     errno       phd         scramble    template    update

However, when learning a subcommand's flags, they apply to the top-level pwn command.

$ pwn phd --help
...
┌──> /Users/zachriggle/.pyenv/shims/pwn phd --help
└─── cod: learn this command? [yn?] >
cod: learned completions: "-h" "--help" "-w" "--width" "-l" and 7 more
$ pwn <tab>
--color     --offset    -c          -o          asm         cyclic      disasm      errno       pwnstrip    template
--count     --skip      -h          -s          checksec    debug       elfdiff     hex         scramble    unhex
--help      --width     -l          -w          constgrep   disablenx   elfpatch    phd         shellcraft  update

Error signal: killed after trying to add python click commandline tool

When running my own tool with the --help flag, cod responds with the following message cod: error: server returned error: signal: killed:. Tried with pre-compiled version as well as with my own build. I am on Mac. Below I have added the log output.

21949 2020/02/04 15:00:40 Received request: {"Request":"ParseCommandLineRequest","Payload":{"Pid":21555,"CommandLine":"videdit --help","Dir":"/Users/bjoosten","Env":["SHELL=/usr/local/bin/bash","ITERM_PROFILE=Default","COLORTERM=truecolor","PYENV_SHELL=bash","XPC_FLAGS=0x0","TERM_PROGRAM_VERSION=3.3.8","SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.W6iqdr4Jqp/Listeners","TERM_SESSION_ID=w0t0p0:7588C440-DC79-4439-BF27-DD9C6861EA94","PWD=/Users/bjoosten","PYENV_VIRTUALENV_INIT=1","LOGNAME=bjoosten","ITERM_SESSION_ID=w0t0p0:7588C440-DC79-4439-BF27-DD9C6861EA94","HOME=/Users/bjoosten","TMPDIR=/var/folders/zs/bt7md3c56xjcqqvz7yhzmyfc0000gq/T/","LC_TERMINAL=iTerm2","TERM=xterm-256color","USER=bjoosten","COLORFGBG=12;8","LC_TERMINAL_VERSION=3.3.8","SHLVL=1","XPC_SERVICE_NAME=0","LC_CTYPE=UTF-8","PYENV_ROOT=/Users/bjoosten/.pyenv","Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.EB0ARoNRPT/Render","PATH=/Users/bjoosten/.pyenv/plugins/pyenv-virtualenv/shims:/Users/bjoosten/.pyenv/shims:/Users/bjoosten/.pyenv/bin:/Users/bjoosten/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin","__CF_USER_TEXT_ENCODING=0x0:0:5","TERM_PROGRAM=iTerm.app","_=/Users/bjoosten/bin/cod"]}}
21949 2020/02/04 15:00:40 Sending response: {"Response":{"IsHelpCommand":true,"PolicyMode":"trust","Args":["/Users/bjoosten/.pyenv/shims/videdit","--help"],"Env":null}}
21949 2020/02/04 15:00:40 Received request: {"Request":"AddHelpPageRequest","Payload":{"Command":{"Args":["/Users/bjoosten/.pyenv/shims/videdit","--help"],"Env":["SHELL=/usr/local/bin/bash","ITERM_PROFILE=Default","COLORTERM=truecolor","PYENV_SHELL=bash","XPC_FLAGS=0x0","TERM_PROGRAM_VERSION=3.3.8","SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.W6iqdr4Jqp/Listeners","TERM_SESSION_ID=w0t0p0:7588C440-DC79-4439-BF27-DD9C6861EA94","PWD=/Users/bjoosten","PYENV_VIRTUALENV_INIT=1","LOGNAME=bjoosten","ITERM_SESSION_ID=w0t0p0:7588C440-DC79-4439-BF27-DD9C6861EA94","HOME=/Users/bjoosten","TMPDIR=/var/folders/zs/bt7md3c56xjcqqvz7yhzmyfc0000gq/T/","LC_TERMINAL=iTerm2","TERM=xterm-256color","USER=bjoosten","COLORFGBG=12;8","LC_TERMINAL_VERSION=3.3.8","SHLVL=1","XPC_SERVICE_NAME=0","LC_CTYPE=UTF-8","PYENV_ROOT=/Users/bjoosten/.pyenv","Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.EB0ARoNRPT/Render","PATH=/Users/bjoosten/.pyenv/plugins/pyenv-virtualenv/shims:/Users/bjoosten/.pyenv/shims:/Users/bjoosten/.pyenv/bin:/Users/bjoosten/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin","__CF_USER_TEXT_ENCODING=0x0:0:5","TERM_PROGRAM=iTerm.app","_=/Users/bjoosten/bin/cod"],"Dir":"/Users/bjoosten"},"Policy":""}}
21949 2020/02/04 15:00:41 Sending response: {"Response":{"HelpPage":{"ExecutablePath":"","Completions":null,"CheckSum":"","Command":{"Args":null,"Env":null,"Dir":""}},"Status":""},"Error":{"Code":1,"Desc":"signal: killed: "}}

Supporting sub-commands

Hello,

So far I'm loving your application.

Just curious, are there any plans to support learning sub-commands?

For example apps that use something like command create volume [volume name]?

Thank you.

cannot build on arm64

can't build on target "darwin\arm64"

tried
git clone https://github.com/dim-an/cod.git cd cod go build

tried:
go get -u github.com/dim-an/cod

tried:
go install github.com/dim-an/cod@latest

PLATFORM: Apple M1 Max - MacOS Ventura 13.0.1 (22A400)
GO VERSION: go1.19.3 darwin/arm64
SHELL: zsh 5.9 (arm-apple-darwin22.1.0)

output of go env

GO111MODULE="" GOARCH="arm64" GOBIN="" GOCACHE="/Users/ambraurso/Library/Caches/go-build" GOENV="/Users/ambraurso/Library/Application Support/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="arm64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/ambraurso/etc/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/ambraurso/etc/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/Users/ambraurso/.asdf/installs/golang/1.19.3/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/Users/ambraurso/.asdf/installs/golang/1.19.3/go/pkg/tool/darwin_arm64" GOVCS="" GOVERSION="go1.19.3" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/dev/null" GOWORK="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/r5/7br76ph52bd61jg9yfqjy_8c0000gn/T/go-build1180376230=/tmp/go-build -gno-record-gcc-switches -fno-common"

cod tries to learn commands which already have completions

zsh already ships with lots of completion scripts.

cod attempts to learn these, even though they already exist.

For example:

$ git add --help
...
┌──> /usr/local/bin/git add --help
└─── cod: learn this command? [yn?] >

cod should probably check zstyle or compdef to determine which autocompletions are already available.

$ zstyle | grep 'completion.*:git'
        :completion:*:*:git:* common-commands

cod should check for existing completions for aliased commands

I have a bunch of wrapper scripts around ripgrep rg, and I alias all of their completions to rg since the arguments get passed-through.

Autocompletion already works in this manner, so cod should not try to learn them.

$ cat bin/example-script
#!/usr/bin/env zsh
rg "$@"
$ example-script <tab>
 -- option --
--after-context                 -A  -- specify lines to show after each match
--and                               -- Logical AND
--auto-hybrid-regex                 -- dynamically use PCRE2 if necessary
--before-context                -B  -- specify lines to show before each match
--binary                            -- search binary files, don't print binary data
--block-buffered                    -- force block buffering
--byte-offset                   -b  -- show 0-based byte offset for each matching line
--case-sensitive                -s  -- search case-sensitively

However, cod tries to learn it when passing --help.

$ example-script --help
...
OPTIONS:
    -A, --after-context <NUM>
...
┌──> /Users/zachriggle/..../bin/example-script --help
└─── cod: learn this command? [yn?] >

Here's how they are registered, tldr is compdef mycommand=rg.

#!/usr/bin/env zsh
BINDIR="${0:h}/bin"
path=("$BINDIR" $path)

for script in "$BINDIR"/*(*); do
    name="$script:t"
    compdef "$name"=rg
done

There is no fpath entry for these, they are just compdef aliases. This should be consulted before offering to learn a command.

cod fails to start on macOs

Getting this error:

cod: error: server returned error: Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub

add support for docopt style help

It would be nice if cod could learn help in the format proposed by docopt http://docopt.org/

for example if i try to make cod learn their default example:

$ ./naval_fate --help
Naval Fate.

Usage:
  naval_fate ship new <name>...
  naval_fate ship <name> move <x> <y> [--speed=<kn>]
  naval_fate ship shoot <x> <y>
  naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate -h | --help
  naval_fate --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.
┌──> /tmp/naval_fate --help                                                                                                                                                                                                         
└─── cod: learn this command? [yn?] > y
cod: learned completions: "--speed=" "--moored" "--drifting" and 3 more

Only flag options are learned. However I'm not sure how wildly spread the docopt format actually is...

fish shell support

When you do cod init --help it lists that you can specify fish as an argument but no script is returned when fish is used.

So does this tool have FISH shell support? If not I would like to request it as it is very popular shell.

Thanks!

Path completion don't work

Can't really come up with good title, sorry. Bad English knowledge.

So, I made bare git repository for my dot files and make alias config for this repo. After config -h cod picked up possible flags and commands as expected. But when I try type something like config add ~/.config/ and press TAB nothing happens.

Use `command cod` in generated scripts

I already have a cod alias, and so the current generated scripts don't work for me. It's far more reliable to use command cod ... in the generated scripts. This is especially true since cod is a 3-lettered word, and so the probability of it already being in use is not negligible.

PS: I am using command cod init $$ zsh | sd '\bcod\b' 'command cod' as a workaround currently.

File completions are not optional

When learning new commands, cod forces the addition of file completions with compgen -f inside __cod_complete_bash, but there is no way to turn this behavior off.

Personally, I think this should at the very least be a toggleable flag. When using menu-completion=on, for example, filenames can really pollute the completions list according to how many files are in the current dir at that moment:
Untitled

A temporary workaround is redefining the __cod_complete_bash function after the init script is sourced and commenting the line below:

	# Generate cod completions.
        #readarray -t COD_COMPLETIONS < <(command $__COD_BINARY api complete-words -- $$ "$COMP_CWORD" "${COMP_WORDS[@]}" 2> /dev/null)
	```

generate completions based on commands usage

This is kind of a long shot, but it might be useful to provide to cod a few example flags or commands, and have it do fuzzy detection for those and infer the rest of them (for when it's a non-standard help format).

Why does it work even after removing the binary?

Hi,

I installed cod by building it using go build. It was working fine for me, I just wanted to try the software, and so for uninstalling, I removed:

  • the associated sym-link I made for it to be called in $PATH
  • source command in my .bashrc
  • cod directory that I cloned and built
  • ~/.local/share/cod

But for some reason, it's still shows the args on pressing tab, even though the binary cod itself is removed. For the trial, I used it on fdfind command and below is the output for above scenario. Also, I'd like to point out, I don't have any cod folder in $HOME/.config.

How can I get back my normal commands tab-completion?

Screenshot from 2020-11-04 03-29-07

cod should attempt to learn flag descriptions

For the basic case of Python argparse-based help menus, it would be useful if cod could also learn the description of the flag (or at least the first line of it).

Compare the following (from the Pwntools repo):

asm --help
usage: pwn asm [-h] [-f {raw,hex,string,elf}] [-o file] [-c context]
               [-v AVOID] [-n] [-z] [-d] [-e ENCODER] [-i INFILE] [-r]
               [line [line ...]]

positional arguments:
  line                  Lines to assemble. If none are supplied, use stdin

optional arguments:
...
  -n, --newline         Encode the shellcode to avoid newlines

Tab completion only shows the flags themselves, and not the helpful descriptive text:

% asm -<tab>
--avoid    --encoder  --infile   --run      -c         -e         -h         -n         -r         -z
--debug    --help     --newline  --zero     -d         -f         -i         -o         -v

The learned autocomplete should show something similar to what is provided with the default Git completion:

$ git --<tab>
 -- option --
--bare                -- treat the repository as a bare repository
--exec-path           -- path to where your core git programs are installed

Such that it might look like this:

$ asm -<tab>
...
-n --newline          -- Encode the shellcode to avoid newlines

cod cannot auto-learn itself

COD appears unable to learn its own subcommands

$ cod list
11	/Users/zachriggle/bin/cod --help
$ cod --help<tab>
--help     --version

Possible to disable on environment variable?

I want to instruct card to only generate completions for specific commands. I do not want to watch for command on each run.

Is there a way to disable card from actively watching for new commands via an environment variable?

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.