Skip to content

Instantly share code, notes, and snippets.

@ocmanv
Created February 24, 2014 10:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ocmanv/9184960 to your computer and use it in GitHub Desktop.
Save ocmanv/9184960 to your computer and use it in GitHub Desktop.
cabal command line completion
# cabal command line completion
# Copyright 2014 "Osman Veliev" <ocmanv@gmail.com>
#
# Реализовано:
# - кеширование списка пакетов - _cabal_cach()
# - автодополнение версии пакета
# - напоминания об устаревшей базе пакетов - _cabal_log()
# - и установленных версиях пакета - _cabal_installed()
# - автодополнение для "cabal list"
# Input: $@
# Output: STDERR
_cabal_echo()
{
if [[ "$1" != "" ]]; then
echo >&2
for i in "$@" ; do
echo "$i" >&2
done
kill -SIGWINCH $$
fi
}
# Input: STDIN
# Output: STDERR
_cabal_log()
{
local IFS=$'\n'
read -t 10 -a line
while read -t 2 ln ; do
line+=("${ln[*]}")
done
_cabal_echo "${line[@]}"
}
# Input: $1
# Output: STDERR
_cabal_installed()
{
local name="$1"
local message=( )
for db in global user ; do
local a="$( ghc-pkg --simple-output --$db list | sed 'y:\ :\n:' | grep -E "^${name}-([.0-9]+)$" )"
[[ "$a" ]] && message+=("Warning: Installed in $db DB: $a")
done
_cabal_echo "${message[*]}"
}
# Input: $cur $cach
# Output: $COMPREPLY
_cabal_packages()
{
local name vers ver
if [[ ${cur} =~ ^(([^.-]+-)+)([.0-9]+)?$ ]]; then
name="${BASH_REMATCH[1]%-}"
ver="${BASH_REMATCH[3]}"
vers=( $( cat "$cach" | grep -E "^${name} " ) )
fi
if [[ "$vers" ]]; then
_cabal_installed "${name}"
# [[ "${COMP_WORDBREAKS}" != *-* ]] && export COMP_WORDBREAKS+=-
# COMPREPLY=( $( compgen -W "${vers[*]:1}" -- "$ver" ) )
COMPREPLY=( $( compgen -P "${name}-" -W "${vers[*]:1}" -- "$ver" ) )
else
# export COMP_WORDBREAKS="${COMP_WORDBREAKS//-}"
COMPREPLY=( $( compgen -W "$( cat ${cach} | cut -d' ' -f1 )" -- "$cur" ) )
fi
}
# Input: $cach
# Output: STDERR file://"$cach"
_cabal_cach()
{
local path="$HOME/.cabal/packages/hackage.haskell.org"
local f="$path/00-index.cache"
local cmd="${words[0]} list --simple-output"
if [[ "$f" -nt "$cach" ]]; then
touch "$cach"
(
_cabal_echo "Caching..."
( $cmd | sed -rn ':a $!N; s:^(.*)( .*)\n\1( .*)$:\1\2\3:; ta; P; D' >"$cach" ) 2>&1 | _cabal_log
_cabal_echo "Cached"
) & >&- <&-
fi
}
_cabal()
{
# export COMP_WORDBREAKS="${COMP_WORDBREAKS//-}"
local cur words cword
_get_comp_words_by_ref -n - cur words cword
local cach="/tmp/bash-completion-cabal"
_cabal_cach
local left="${words[*]:1:(($cword-1))}"
if [[ "$cur" != -* && " ${left} " =~ \ (install|list|info|fetch|get)\ ]]; then
if [[ ${BASH_REMATCH[1]} == list ]]; then
COMPREPLY=( $( cat ${cach} | cut -d' ' -f1 | grep -i "$cur" ) )
else
_cabal_packages
fi
else
local cmd=( ${words[@]} )
cmd[${cword}]="--list-options"
COMPREPLY=( $( compgen -W "$( ${cmd[@]} )" -- $cur ) )
fi
}
complete -F _cabal -o default cabal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment