public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] gentoo-completion update
@ 2002-01-17 18:52 Zach Forrest
  2002-01-17 19:11 ` Bart Verwilst
  2002-01-17 23:54 ` Jason Ritchie
  0 siblings, 2 replies; 5+ messages in thread
From: Zach Forrest @ 2002-01-17 18:52 UTC (permalink / raw
  To: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 650 bytes --]

Good morning. I've made some improvements to the Gentoo bash completion 
facilities.

Changes/Improvements:
- added "--world" to the list of options
- when completing on multiple options, only options that have not
   already been specified are listed
- fixed the behaviour [Canadian spelling] whereby options could be
   specified after packages
- "system" and "update" options do not appear if packages have been
   specified already, and must appear alone (this seems to make sense,
   but I'm not sure if this is the correct behaviour -- can you do
   something like "emerge --pretend update cat1/pkg1 cat2/pkg2"? --
   please let me know)

Zach

[-- Attachment #2: gentoo.completion --]
[-- Type: text/plain, Size: 10152 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>
#
# Note: Geert did the bulk of the work, I've just add a few features. -zach
#

# 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

	origdir="${PWD}"
	portagedir=/usr/portage

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	prev=${COMP_WORDS[COMP_CWORD-1]}

	if [ $COMP_CWORD -eq 1 ] && [ ${#COMP_WORDS[*]} -eq 2 ] && [[ "$cur" == -* ]]; then
		# making sure that nothing exists besides this (the current
		# element) and the emerge command allows the "--clean" option
		# to be filtered out (see below)
		COMPREPLY=( $( compgen -W '--autoclean \
			--buildpkg \
			--clean \
			--debug \
			--fetchonly \
			--help \
			--noreplace \
			--onlydeps \
			--pretend \
			--usepkg \
			--verbose \
			--world' | grep ^$cur ) )

	elif [ "$prev" == "--clean" ]; then
		# "rsync" is the only option that can follow "--clean"
		COMPREPLY=( $( compgen -W 'rsync' ) )

	elif [ "$prev" == "--world" ]; then
		# "update" is the only option that can follow "--world"
		COMPREPLY=( $( compgen -W 'update' ) )

	elif [ "$prev" == "rsync" ] || [ "$prev" == "update" ] || [ "$prev" == "system" ]; then
		# syncing the portage tree is a lonely job
		# updating should be done by itself (also lonely)
		COMPREPLY=''

 	#elif [[ " ${COMP_WORDS[*]} " == *" "*@(update|system|rsync)*" "* ]]; then
 	#	COMPREPLY=''

	elif [[ "$cur" == -* ]] && [[ ! " ${COMP_WORDS[*]} " == *" "*[/.]*" "* ]]; then
		# this allows for multiple options to be specified
		# after the emerge command (i.e. no packages yet)
		# the "--clean" option is no longer available

		COMPREPLY=( $( compgen -W '--autoclean \
			--buildpkg \
			--debug \
			--fetchonly \
			--help \
			--noreplace \
			--onlydeps \
			--pretend \
			--usepkg \
			--verbose \
			--world' | grep ^$cur ) )

		# (Adapted from bash_completion by Ian Macdonald <ian@caliban.org>)
		# this removes any options from the list of completions that have
		# already been specified somewhere 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[@]})
 		  ) )

	elif [[ " ${COMP_WORDS[*]} " == *" --usepkg "* ]]; then
		# This case currently has the limitation of not completing
		# on packages in /usr/portage. Instead it defaults to
		# normal bash completion so a path to the package can
		# be specified.
		COMPREPLY=( $( compgen $cur ) )

	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 /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 [[ ! " ${COMP_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
		
	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

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2002-01-18  0:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-01-17 18:52 [gentoo-dev] gentoo-completion update Zach Forrest
2002-01-17 19:11 ` Bart Verwilst
2002-01-17 22:35   ` Zach Forrest
2002-01-17 23:54 ` Jason Ritchie
2002-01-18  0:06   ` Geert Bevin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox