From: Zach Forrest <zach@disinformation.ca>
To: gentoo-dev@gentoo.org
Subject: [gentoo-dev] latest and greatest gentoo.completion
Date: Tue, 12 Mar 2002 17:05:15 -0800 [thread overview]
Message-ID: <3C8EA5CB.5070108@disinformation.ca> (raw)
[-- Attachment #1: Type: text/plain, Size: 136 bytes --]
I've made some significant changes incorporating the latest available
options and making the completion more intelligent. Enjoy!
Zach
[-- Attachment #2: gentoo.completion --]
[-- Type: text/plain, Size: 13297 bytes --]
# -*- shell-script -*-
#
# Gentoo Linux command completion.
#
# Copyright 1999-2002 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License, v2 or later
#
# Author: Geert Bevin <gbevin@theleaf.be>
# Author: Zach Forrest <zach@disinformation.ca>
#
# Turn on extended globbing and programmable completion
shopt -s extglob progcomp
#
# emerge completion command
#
_emerge()
{
local cur prev grepcmd sedcmd systemactions setsma setbig portagedir origdir
local mode words opts curword numwords pkgdbdir
origdir="${PWD}"
portagedir=/usr/portage
pkgdbdir=/var/db/pkg
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
words="${COMP_WORDS[*]}"
numwords=${#COMP_WORDS[*]}
curword=${COMP_CWORD}
mode='ALL'
# Determine which mode we're running in.
if [ ${curword} -eq 1 ] && [ ${numwords} -eq 2 ]; then
# This is set when we nothing but the command name has been given.
mode='ALL'
elif [[ " ${words} " == *" --unmerge "* ]]; then
mode='UNMERGE'
elif [[ " ${words} " == *" --safe "* ]]; then
mode='SAFE'
elif [[ " ${words} " == *" --search "* ]]; then
mode='SEARCH'
elif [[ " ${words} " == *" --world "* ]]; then
mode='WORLD'
elif [[ " ${words} " == *" --help "* ]]; then
mode='HELP'
elif [[ " ${words} " == *" --clean "* ]]; then
mode='CLEAN'
elif [[ " ${words} " == *" --pretend "* ]]; then
mode='PRETEND'
else
# All except '--clean'
mode='NOCLEAN'
fi
if [[ "${cur}" == -* ]]; then
# Process Options
case "${mode}" in
"ALL")
opts='--clean --help --verbose --debug --fetchonly \
--onlydeps --noreplace --usepkg --buildpkg \
--autoclean --pretend --unmerge --safe \
--search --world'
;;
"UNMERGE")
opts='--clean --verbose --debug --pretend \
--unmerge --safe'
;;
"SAFE")
opts='--unmerge --verbose --debug'
;;
"SEARCH")
opts='--verbose --debug'
;;
"WORLD")
opts='--verbose --debug --pretend --world'
;;
"HELP")
opts=''
;;
"CLEAN")
opts='--verbose --debug --clean'
;;
"PRETEND")
opts='--verbose --debug --fetchonly --onlydeps \
--noreplace --usepkg --buildpkg \
--autoclean --pretend --unmerge --safe \
--world'
;;
"NOCLEAN")
opts='--help --verbose --debug --fetchonly \
--onlydeps --noreplace --usepkg --buildpkg \
--autoclean --pretend --unmerge --safe \
--search --world'
;;
*)
# Same as ALL
opts='--clean --help --verbose --debug --fetchonly \
--onlydeps --noreplace --usepkg --buildpkg \
--autoclean --pretend --unmerge --safe \
--search --world'
;;
esac
# Generate the reply.
COMPREPLY=($(compgen -W "${opts}" | grep ^$cur))
elif [ "${mode}" == "CLEAN" ]; then
# "rsync" is the only option that can follow "--clean"
COMPREPLY=($(compgen -W 'rsync'))
elif [ "${mode}" == "WORLD" ]; then
# "update" is the only option that can follow "--world"
#COMPREPLY=($(compgen -W 'update'))
COMPREPLY=($(compgen -W 'update' | grep ^${cur}))
elif [ "${mode}" == "HELP" ]; then
if [[ ! " ${words} " == *" "@(system|rsync)" "* ]]; then
COMPREPLY=($(compgen -W 'rsync system' | grep ^${cur}))
else
COMPREPLY=''
fi
elif [ "${mode}" == "SEARCH" ]; then
# We don't need to interfere here as the search string is a
# regular expression. (But wouldn't intelligent, dynamic,
# commandline completion of regular expressions be great!)
COMPREPLY=''
elif [ "${mode}" == "UNMERGE" ]; then
# Ignore >, >=, <, <=, and = for the purpose of completion.
sedcmd="sed -e s:=:: -e s:>:: -e s:<::"
cur=$(echo "${cur}" | ${sedcmd})
# If the current completion (minus conditional characters)
# starts with one of the following characters, then complete
# on filenames (i.e. an ebuild file) rather than referencing
# the package database.
if [[ "${cur} " == @('/'|'.'|'~'|'$')* ]]; then
# Setting this to nothing with tell bash to use default
# completion (i.e. pathname completion).
COMPREPLY=''
else
cd "${pkgdbdir}"
grepcmd="grep -E ^$cur.*"
if [ "${cur}" ]; then
if [ $(echo "${cur}" | grep '/') ]; then
setbig=$(compgen -G "${cur}*")
COMPREPLY=($(echo "${setbig}" | ${grepcmd}))
else
setsma=$(compgen -S '/' -G "${cur}*")
if [ $(echo "${setsma}" | ${grepcmd} | grep '/' | wc -l) = 1 ]; then
setbig=$(compgen -G "*/*")
COMPREPLY=($(echo "${setbig}" | ${grepcmd}))
else
COMPREPLY=($(echo "${setsma}" | ${grepcmd}))
fi
fi
else
setsma=$(compgen -S '/' -G "${cur}*")
COMPREPLY=($(echo "${setsma}"))
fi
cd "${origdir}"
fi
elif [ "${mode}" == "SAFE" ]; then
COMPREPLY=($(compgen -W '--unmerge' | grep ^${cur}))
elif [[ " ${words} " == *" "@(update|system|rsync)" "* ]]; then
# syncing the portage tree is a lonely job
# updating should be done by itself (also lonely)
COMPREPLY=''
elif [[ " ${words} " == *" --usepkg "* ]] && [[ "${cur} " == @('/'|'.'|'~'|'$')* ]]; then
# In order to complete on a package file, the name must be
# an absolute or realative pathname (even if it is in the
# current directory). This allows completion on both package
# names in /usr/portage and on arbitrary *.tbz2 packages.
#
# I'm planning to come up with a more elegant solution, but
# that will have to wait for another update. (The only thing
# that is really annoying right now is when specifying a
# *.tbz2 file in or below the current directory, you have
# to prefix the path with "./".)
COMPREPLY=''
else
cd "${portagedir}"
grepcmd="grep -E ^${cur}.*"
sedcmd="sed -e /CVS/d \
-e /BUGS-TODO/d \
-e /ChangeLog.*/d \
-e /header.txt/d \
-e /skel.build/d \
-e /skel.ebuild/d \
-e /distfiles/d \
-e /eclass/d \
-e /files/d \
-e /incoming/d \
-e /packages/d \
-e /profiles/d \
-e /scripts/d \
-e /virtual-update/d \
-e /current-packages/d"
if [ ${COMP_CWORD} -eq 1 ]; then
# If emerge hasn't been given any args yet, include "rsync"
# among the system actions. The case where the "--clean" flag
# has been specified is handled above.
systemactions=$'\n'"system"$'\n'"update"$'\n'"rsync"
else
# Only allow these actions if no packages have been specified.
if [[ ! " ${words} " == *" "*[/]*" "* ]]; then
systemactions=$'\n'"system"$'\n'"update"
else
systemactions=''
fi
fi
if [ "${cur}" ]; then
if [ $(echo "${cur}" | grep '/') ]; then
setbig=$(compgen -G "${cur}*" | ${sedcmd})"${systemactions}"
COMPREPLY=($(echo "${setbig}" | $grepcmd))
else
setsma=$(compgen -S '/' -G "${cur}*" | ${sedcmd})"${systemactions}"
if [ $(echo "${setsma}" | ${grepcmd} | grep '/' | wc -l) = 1 ]; then
setbig=$(compgen -G "*/*" | ${sedcmd})"${systemactions}"
COMPREPLY=($(echo "${setbig}" | ${grepcmd}))
else
COMPREPLY=($(echo "${setsma}" | ${grepcmd}))
fi
fi
else
setsma=$(compgen -S '/' -G "${cur}*" | ${sedcmd})"${systemactions}"
COMPREPLY=($(echo "${setsma}"))
fi
cd "${origdir}"
fi
# (Adapted from bash_completion by Ian Macdonald <ian@caliban.org>)
# This removes any options from the list of completions that have
# already been specified on the command line.
COMPREPLY=($(echo "${COMP_WORDS[@]}" | \
(while read -d ' ' i; do
[ "${i}" == "" ] && continue
# flatten array with spaces on either side,
# otherwise we cannot grep on word boundaries of
# first and last word
COMPREPLY=" ${COMPREPLY[@]} "
# remove word from list of completions
COMPREPLY=(${COMPREPLY/ ${i%% *} / })
done
echo ${COMPREPLY[@]})))
return 0
}
complete -o default -F _emerge emerge
#
# ebuild completion command
#
_ebuild()
{
local cur prev
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
if [ $COMP_CWORD -eq 1 ]; then
#COMPREPLY=( $( compgen -o filenames -X '!*.ebuild' $cur ) )
COMPREPLY=( $( compgen -o filenames ) )
elif [ $COMP_CWORD -eq 2 ]; then
COMPREPLY=( $( compgen -W 'clean \
compile \
digest \
fetch \
install \
merge \
package \
qmerge \
remerge \
rpm \
unmerge \
unpack' $cur ) )
fi
return 0
}
complete -o default -F _ebuild ebuild
#
# rc-update completion command
#
_rc-update()
{
local cur prev initdir runlvdir origdir
origdir=${PWD}
initdir=/etc/init.d
runlvdir=/etc/runlevels
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
if [ $COMP_CWORD -eq 1 ]; then
COMPREPLY=( $( compgen -W 'add del' ${cur} ) )
elif [ $COMP_CWORD -eq 2 ]; then
cd ${initdir}
COMPREPLY=( $( compgen -G "${cur}*" ) )
cd ${origdir}
elif [ $COMP_CWORD -eq 3 ]; then
cd ${runlvdir}
COMPREPLY=( $( compgen -G "${cur}*" ) )
cd ${origdir}
fi
return 0
}
complete -F _rc-update rc-update
#
# This function loosely emulates emerge, but, as the name implies,
# it _unmerges_. It is useful for unmerging multiple, existing packages
# with a lot less typing. It looks in /var/db/pkg.
#
epurge() {
local pkg pkgdb pkgfile usage pretend red yellow off
local pkgnover pkgcount depend
red="\033[31;01m" # Red
yellow="\033[33;01m" # Yellow
off="\033[0m" # Default
pkgdb="/var/db/pkg"
usage="Usage: ${FUNCNAME} [ --pretend ] cat/pkg [ [ cat2/pkg2 ] ... ]"
count=0
# We need at least one package
if [ -z "${1}" ]; then
echo "${usage}"
return 1
fi
if [ "${1}" = "--pretend" ]; then
# We need at least one package
if [ -z "${2}" ]; then
echo "${usage}"
return 1
else
shift # move "--pretend" out of the way
pretend="TRUE"
echo
echo "These are the packages that I would unmerge, in order."
fi
fi
# The following may seem a little overzealous. After all, why not just check
# for the existence of the files during the main loop? My rationale is this:
# because unmerging has the potential to do serious damage (e.g. unmerging your
# only glibc entry), any problems should be addressed _before_ any packages are
# unmerged. This will provide one extra sanity check for the user; if there
# is one mistake, there may be others. Also, because this function isn't the
# most sophisticated piece of code in the world, if a package was specified
# more than once on the command line, the main loop can now assume (with a
# reasonable degree of certainty) that any missing ebuild files are from
# packages that have already been unmerged (i.e. if the file doesn't exist,
# it must have been unmerged with a previous call to ebuild).
# Enough talk....
for pkg in $*
do
pkgfile="${pkgdb}/${pkg}/$( basename ${pkg} ).ebuild"
if [ ! -f "${pkgfile}" ]; then
echo
echo -e "${red}!!!${off} Cannot find database entry for $pkg:"
echo -e "${red}!!!${off} $pkgfile not found"
echo
return 1
fi
done
# Make some room.
echo
for pkg in $*
do
if [ "${pretend}" = "TRUE" ]; then
echo -e "[ebuild ${red}UNMERGE${off}] $pkg"
# Calculate dependencies
#
# Note: This doesn't (yet) account for version numbers
# in calculating dependencies. So, if a package requires
# a specific version of the one being unmerged, and this
# is that version, then you may end up with a broken
# package/dependency. Also, dependency checking is only
# performed when using "--pretend". When actually
# unmerging packages, it is assumed that you know what
# you are doing.
#
# TODO: make version aware
# TODO: check for PROVIDES (i.e. virtual dependencies)
pkgnover="${pkg%%-[0-9]*}"
pkgcount=$( ls "${pkgdb}/${pkg%%/*}" | grep -c ${pkgnover##*/} )
# If there exists another installed version of the package,
# then assume any dependencies are taken care of (see note
# above). Otherwise, check for packages dependent on this
# one.
if [ ${pkgcount} -eq 1 ]; then
for depend in $( egrep -l ${pkgnover} $( find ${pkgdb} -name RDEPEND ) \
| sed -e "s|/RDEPEND||" -e "s|${pkgdb}/||" )
do
echo -e "${yellow}!!! WARNING:${off} $depend depends on $pkgnover"
done
fi
else
pkgfile=${pkgdb}/${pkg}/$( basename ${pkg} ).ebuild
if [ -f "${pkgfile}" ]; then
echo ">>> Unmerging ${pkg}...."
echo ">>> ebuild ${pkgfile} unmerge"
ebuild ${pkgfile} unmerge
echo ">>> ${pkg} unmerged"
else
echo
echo "!!! Ignoring ${pkg} (already unmerged)" # most likely, anyway
echo
fi
fi
done
echo
return 0
}
#
# epurge completion command
#
_epurge()
{
local cur origdir pkgdb grepcmd setsma setbig
origdir="${PWD}"
pkgdb=/var/db/pkg
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then
COMPREPLY=( $( compgen -W '--pretend' | grep ^$cur ) )
else
cd ${pkgdb}
grepcmd="grep -E ^${cur}.*"
setsma=$( compgen -S '/' -G "*" )
setbig=$( compgen -G "*/*" )
if [ ${cur} ]; then
if [ `echo ${cur} | grep '/'` ]; then
COMPREPLY=( $( echo "${setbig}" | ${grepcmd} ) )
else
if [ `echo "${setsma}" | ${grepcmd} | grep '/' | wc -l` = 1 ]; then
COMPREPLY=( $( echo "${setbig}" | ${grepcmd} ) )
else
COMPREPLY=( $( echo "${setsma}" | ${grepcmd} ) )
fi
fi
else
COMPREPLY=( $( echo "${setsma}" ) )
fi
cd ${origdir}
fi
return 0
}
complete -F _epurge epurge
next reply other threads:[~2002-03-13 0:59 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-03-13 1:05 Zach Forrest [this message]
2002-03-13 6:48 ` [gentoo-dev] latest and greatest gentoo.completion Thilo Bangert
2002-03-13 18:30 ` Zach Forrest
2002-03-13 18:56 ` Thilo Bangert
2002-03-14 22:38 ` jboyens
2002-03-16 17:56 ` Ian Smith
2002-03-16 18:05 ` Gerald Schneider
2002-03-16 18:27 ` Ian Smith
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3C8EA5CB.5070108@disinformation.ca \
--to=zach@disinformation.ca \
--cc=gentoo-dev@gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox