cod is a completion daemon for bash/fish/zsh

Overview

https://github.com/dim-an/cod/workflows/Go/badge.svg

Cod is a completion daemon for {bash,fish,zsh}.

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

https://asciinema.org/a/h0SrrNvZVcqoSM4DNyEUrGtQh.svg

Install

Download or build cod binary for your OS and put it into your $PATH.

Then you need to edit your init script and add few lines.

Bash

Add to ~/.bashrc

source <(cod init $$ bash)

Zsh

Add to ~/.zshrc

source <(cod init $$ zsh)

Fish

Add to ~/.config/fish/config.fish

cod init %self fish | source

Supported shells and operating systems

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

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.

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

Build

Go v1.16 is recommended.

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:

  • checks if --help flag is used;
  • checks that command is simple i.e. doesn’t contain any pipes, file descriptor redirections, and other shell magic;
  • 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 program. (So it finds binary in PATH or resolves relative path if required). Other arguments except binary path are left unchanged.

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

If program is successfully executed cod will store:

  • absolute path to binary;
  • used arguments;
  • 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 of help pages and recognizes flags (starting with -) but doesn’t recognize subcommands.

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

Configuration

Cod will search config in $XDG_CONFIG_HOME/cod/config.toml file (default: ~/.config/cod/config.toml).

Config file allows to specify rules to ignore executables or always trust them.

cod example-config prints example configuration to stdout. cod example-config --create writes example configuration to proper config file.

Data directories

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

Comments
  • Why does it work even after removing the binary?

    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

    opened by maniac-en 9
  • Add new release

    Add new release

    Adding a new release would allow a homebrew config to automatically install a more recent version.

    Here's the PR on homebrew https://github.com/Homebrew/homebrew-core/pull/75589

    opened by iloveitaly 6
  • fish shell support

    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!

    accepted 
    opened by lordlycastle 3
  • Supporting sub-commands

    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.

    opened by bashfulrobot 3
  • Which file to sync to share the learned completions between my machines?

    Which file to sync to share the learned completions between my machines?

    I currently use YADM to sync all my configs, as well as my fish completions.

    I would like to share the cod learned completions as well.

    I am not sure which/if there is a file that I should sync, it seems like you store the completions in a sqlite database.

    Thanks for any help

    opened by IndianBoy42 2
  • cod doesn't parse help of nxserver correctly

    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.

    opened by nodswal 2
  • Error signal: killed after trying to add python click commandline tool

    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: "}}
    
    opened by Bartcardi 2
  • Fix Go module path

    Fix Go module path

    By using the correct (full-qualified) module path, go get builds the binary and copies it into the directory named by the GOBIN environment variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH environment variable is not set.

    opened by gschauer 1
  • Convert spaces to tabs

    Convert spaces to tabs

    to generate consistent init script

    This fixes the following aesthetic mismatch:

            local FILE_COMPLETIONS
            local COD_COMPLETIONS
            # Generate file completions
            readarray -t FILE_COMPLETIONS < <(compgen -f -X "$FILTEROPT" -- "$2")
    
            # Generate cod completions.
        readarray -t COD_COMPLETIONS < <(cod api complete-words -- $$ "$COMP_CWORD" "${COMP_WORDS[@]}" 2> /dev/null)
    
            COMPREPLY=("${FILE_COMPLETIONS[@]}" "${COD_COMPLETIONS[@]}")
    
            local NAME
            local ONLY_EQ=true
            # Now we don't want bash to add trailing space for options that end with '='
            for NAME in "${COD_COMPLETIONS[@]}" ; do
                    if [ "${NAME: -1}" != "=" ] ; then
    
    
    opened by SuperSandro2000 1
  • cod is incompatible with functions that contain `@` in their names

    cod is incompatible with functions that contain `@` in their names

    ❯ @opts engine rgf pattern '([^:]*):()(.*)' @ ntl.
    ...
    
    cod: error: failed to open arguments file "opts engine rgf pattern '([^:]*):()(.*)' @ ntl.": open opts engine rgf pattern '([^:]*):()(.*)' @ ntl.: no such file or directory, try --help
    
    accepted 
    opened by NightMachinery 1
  • Use `command cod` in generated scripts

    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.

    accepted 
    opened by NightMachinery 1
  • cannot build on arm64

    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"

    opened by aaurso 1
  • File completions are not optional

    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)
    	```
    opened by esauvisky 2
  • add support for docopt style help

    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...

    opened by zeteref 3
  • Path completion don't work

    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.

    opened by Strongleong 7
  • Move socket to `$XDG_RUNTIME_DIR/cod`

    Move socket to `$XDG_RUNTIME_DIR/cod`

    Currently, cod's socket and lock file are placed at $XDG_DATA_DIR/cod/var, which isn't a particularly standard location for them.

    The XDG Base Directory Specification specifies the locations which various files should be stored at. It states:

    There is a single base directory relative to which user-specific runtime files and other file objects should be placed. This directory is defined by the environment variable $XDG_RUNTIME_DIR.

    It further states a fallback for when the variable isn't set:

    If $XDG_RUNTIME_DIR is not set applications should fall back to a replacement directory with similar capabilities and print a warning message.

    This PR changes it so that cod will use $XDG_RUNTIME_DIR/cod for the socket & lockfile when $XDG_RUNTIME_DIR is set, and will fall back upon $XDG_DATA_DIR/cod/var. Since $XDG_RUNTIME_DIR has no default value, falling back upon the old seems like the best choice there.

    In my experience, $XDG_RUNTIME_DIR is usually set by pam_systemd, and ends up being set to /run/user/$UID (which it creates it as a tmpfs). However, I'd prefer to just go with general spec compliance here.

    I'm probably not the best with Go programming, but I think this implementation should work fine.

    opened by BurnerWah 4
Releases(v0.1.0)
Owner
Dmitry Ermolov
Dmitry Ermolov
A command tool to help user install oh-my-zsh plugins fast in a comfortable way

zshx A command tool to help user install oh-my-zsh plugins fast in a comfortable way. in other way, it is a zsh plugin package manager. How to use the

xylon 6 Feb 11, 2022
git-glimpse is a command-line tool that is aimed at generating a git prompt like the one from zsh-vcs-prompt.

Git GoGlimpse git-glimpse is a command-line tool that is aimed at generating a git prompt like the one from zsh-vcs-prompt. The particularity of this

Corentin de Boisset 0 Jan 27, 2022
Fully featured Go (golang) command line option parser with built-in auto-completion support.

go-getoptions Go option parser inspired on the flexibility of Perl’s GetOpt::Long. Table of Contents Quick overview Examples Simple script Program wit

David Gamba 46 Dec 14, 2022
Pure Go command line prompt with history, kill-ring, and tab completion

Prompt Prompt is a command line prompt editor with history, kill-ring, and tab completion. It was inspired by linenoise and derivatives which eschew u

Peter Mattis 1 Nov 20, 2021
Simple trie based auto-completion engine implementation in golang.

Simple auto-complete engine implementation in golang. Quick start $ git clone https://github.com/benbarron/trie-auto-completion-engine $ cd trie-auto-

Ben Barron 1 Jul 12, 2022
command argument completion generator for spf13/cobra

Command argument completion generator for cobra. You can read more about it here: A pragmatic approach to shell completion.

null 73 Dec 26, 2022
argv - Go library to split command line string as arguments array using the bash syntax.

Argv Argv is a library for Go to split command line string into arguments array. Documentation Documentation can be found at Godoc Example func TestAr

null 37 Nov 19, 2022
Go-Suit is a very very wacky version of a bash terminal but in go, however with a little twitst

Go-Suit Go-Suit is a very very wacky version of a bash terminal but in go, however with a little twitst languages -> Go-Lang packages Third Party -> g

RE43P3R 0 May 19, 2022
🖼️ A command-line system information tool written in bash 3.2+

A command-line system information tool written in bash 3.2+ Neofetch is a command-line system information tool written in bash 3.2+. Neofetch displays

dylan 16.9k Dec 30, 2022
A tiny cli command/daemon for syncing toggl time entries with Jira

toggl-sync A tiny cli command/daemon for syncing toggl time entries with Jira Installation Install the app via brew package manager. brew tap timemate

TimeMate 2 Nov 30, 2021
Golang daemon to update i3 workspace icons

i3-icons-daemon Is a lightweight golang daemon service that updates your i3 workspace based on the programs that are running in your workspace's windo

Diogo Fernandes 9 Jul 29, 2022
A daemon to make your keyboard backlight smart.

keyboard-backlight-daemon A daemon to make your keyboard backlight smart. Features Light up keyboard backlight based on user interaction (keyboard, mo

Markus Ressel 0 Jan 17, 2022
bash completion written in go + bash completion for go command

complete Package complete is everything for bash completion and Go. The main development is done on the master branch, please follow the link to see a

Eyal Posener 868 Dec 20, 2022
Highly configurable prompt builder for Bash, ZSH and PowerShell written in Go.

Go Bullet Train (GBT) Highly configurable prompt builder for Bash, ZSH and PowerShell written in Go. It's inspired by the Oh My ZSH Bullet Train theme

Jiri Tyr 520 Dec 17, 2022
bash completion for go and wgo

Source go-pkg-complete.bash.inc to get tab completion for the go tool. Hitting tab after {go,wgo} will complete to any of the standard go subcommands.

John Asmuth 42 Dec 6, 2022
🌳 Go Bonzai™ File Completer, normal completion looking at files and directories with trailing slashes on directories (like bash)

?? Go Bonzai™ File Completer, normal completion looking at files and directories with trailing slashes on directories (like bash)

Rob Muhlestein 2 Apr 12, 2022
Go fish for AWS EIPs

EIP Fishing This is an AWS Lambda that runs a small Go binary on a schedule. Each execution of the binary will allocate an Elastic IP (EIP) in the reg

Tim Koopmans 36 Dec 2, 2022
Fishfindr - An application that is being developed to help me figure out the best places to fish based on my catch history

fishfindr Fishfindr is an application that is being developed to help me figure out the best places to fish based on my catch history. The front-end p

Jake Correnti 2 Feb 10, 2022
A command tool to help user install oh-my-zsh plugins fast in a comfortable way

zshx A command tool to help user install oh-my-zsh plugins fast in a comfortable way. in other way, it is a zsh plugin package manager. How to use the

xylon 6 Feb 11, 2022
git-glimpse is a command-line tool that is aimed at generating a git prompt like the one from zsh-vcs-prompt.

Git GoGlimpse git-glimpse is a command-line tool that is aimed at generating a git prompt like the one from zsh-vcs-prompt. The particularity of this

Corentin de Boisset 0 Jan 27, 2022