parent
06be5e27dc
commit
8448beeb62
@ -0,0 +1,5 @@
|
||||
AUX boodle-ui-qt.py 12114 SHA256 b2a0ea4dc175e7e175671bfca48bafe44a0bd37801babcd7e23e492ad34130a4 SHA512 c2770590a888c8e6183bd173ed484bf487e678679d60e2b8de3335cdc78e04eae9e381f831c6c66be6f3b7ceb4002cd46d4f4598d55f3f76bc686a54487610cc WHIRLPOOL 9aade76ecaccebe4146851e92015388348d0fdc0c467932e142cefb08b01706784d0d72857889a69418f90547328e184a415473a44ef894d6531c17abf8d7333
|
||||
AUX boodler 2156 SHA256 b2f5fbc14dc152e78fdaca0b23020a8df03956c1987ce379df8cf082937177a1 SHA512 88b4e9ae3f916c02ce76a1f7db9ade5b0a24558d3167e16de051f8e1e3cf734b3845b30b9ac26baa231d34b2a0e73c28ce613f11ae14f606495e6619e489f499 WHIRLPOOL 9466af082362125d5adf69143e964cba1bebe608bc3ed668d7da84d51f5e580588141126a53561d43ac0cd9f650e8c7cbbf38a738229a00a5549a830ca687c98
|
||||
DIST Boodler-2.0.4.tar.gz 310801 SHA256 430ca92103203442b1f4c5067ea7f6dc0dbced534bf02a28ed7a8e358aaa55f2 SHA512 d48eb55e552f157e5ec7c456a17f70ec81a7b30fdbe7c7097163c3ee9ae33d726011aecfaecc8c47de8c358eb3b0f46dc0d94fcbe56efa4225e8a2e94e485215 WHIRLPOOL 467dfd1ae8d4d845b5c853cdea5f892c09e7d80c3fb4a571dc5faa509e47586451fb22ed7446537c9363827c89f28343a3831a8f9f02851e4289cc292b1aca5f
|
||||
EBUILD boodler-2.0.4-r1.ebuild 3191 SHA256 3dc47b0043868b78a1c54259c99b24748de6d58994f163a7ce74970ce75f610f SHA512 7afc523a2aac265254d115eab4886c3e163d5c58dba10e847afe7852f72e5dea9d003411b32a50612d4b319b1e4e161831cd847bc56e2116f7e60cf4a19bf8c2 WHIRLPOOL 43ae7da35a550e0952819a84ecec5a6ea3cc29d85583c2e8db233798c54af5e0c37c6ebde62c473b34fd5b5b1db79233e50a743f961061c0944d6406430c2721
|
||||
MISC metadata.xml 457 SHA256 dde8c156d6ec0e6f3dbe3625c2e905d72d736e68f2a86160bd1d84eb5f90b72a SHA512 023ae1900518cb71d67045a02fa33e8b66d4ef1de2ebd842919cb3299baf84aad54d8f47ca865351b65ee484e21a2ad90a789b659275d634e5c15f30d24ce3b5 WHIRLPOOL 8343875e6be7e0f54a02cd4cf7dea695922757158bb1540e56411be392db8d9c1a78101ec2c97880d711477a133a5a7666c9e6ee28cbf13aed9d5559210f237b
|
@ -0,0 +1,111 @@
|
||||
# Copyright 1999-2018 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
EAPI=6
|
||||
PYTHON_COMPAT=( python{2_5,2_6,2_7} )
|
||||
inherit distutils-r1 bash-completion-r1
|
||||
|
||||
DESCRIPTION="Tool for creating soundscapes -- continuous, infinitely varying streams of sound"
|
||||
HOMEPAGE="http://boodler.org/"
|
||||
RESTRICT="mirror"
|
||||
SRC_URI="http://boodler.org/dl/Boodler-${PV}.tar.gz"
|
||||
LICENSE="LGPL-2 GPL-2 public-domain"
|
||||
SLOT="0"
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
IUSE="alsa bash-completion coreaudio doc intmath jack lame qt4 shout vorbis"
|
||||
REQUIRED_USE="shout? ( vorbis )"
|
||||
|
||||
RDEPEND="alsa? ( >=media-libs/alsa-lib-1.0.17a )
|
||||
jack? ( >=media-libs/bio2jack-0.9 )
|
||||
lame? ( >=media-sound/lame-3.98.2-r1 )
|
||||
shout? ( >=media-libs/libshout-2.1 )
|
||||
vorbis? ( >=media-libs/libvorbis-1.2.1_rc1-r2 )"
|
||||
DEPEND="${RDEPEND}
|
||||
qt4? ( >=dev-python/PyQt4-4.7.3[X] )"
|
||||
|
||||
S=${WORKDIR}/Boodler-${PV}
|
||||
|
||||
HTML_DOCS=( doc/ )
|
||||
|
||||
python_prepare_all() {
|
||||
# fix bash completion script for new file names without extension in 2.0.4
|
||||
cp "${FILESDIR}/boodler" "${T}"/boodler || die
|
||||
sed -i -e s/\.py//g "${T}"/boodler || die
|
||||
|
||||
distutils-r1_python_prepare_all
|
||||
}
|
||||
|
||||
python_prepare() {
|
||||
if use qt4 ; then
|
||||
# copy to tmp dir so it can be modified later
|
||||
cp "${FILESDIR}"/boodle-ui-qt.py \
|
||||
"${T}"/${EPYTHON}/boodle-ui-qt || die
|
||||
|
||||
# fix up the command name which was changed in boodler-2.0.4
|
||||
sed -i -e "s/\"boodler.py\"/\"boodler\"/" \
|
||||
"${T}"/${EPYTHON}/boodle-ui-qt || die
|
||||
fi
|
||||
|
||||
distutils-r1_python_prepare
|
||||
}
|
||||
|
||||
python_configure_all() {
|
||||
local defdriver
|
||||
local with
|
||||
local without
|
||||
|
||||
# set up a default audio driver (not daemon) according to USE flags.
|
||||
# it does not appear to work in setup.cfg so there is a workaround below.
|
||||
if use coreaudio ; then
|
||||
defdriver=macosx
|
||||
elif use alsa ; then
|
||||
defdriver=alsa
|
||||
else
|
||||
defdriver=oss
|
||||
fi
|
||||
|
||||
# this ugly code enables/disables the output drivers
|
||||
# oss seems to be needed for boodler.py --list-drivers to work
|
||||
with="${with}oss,"
|
||||
use alsa && with="${with}alsa," || without="${without}alsa,"
|
||||
use coreaudio && with="${with}macosx,osxaq," \
|
||||
|| without="${without}macosx,osxaq,"
|
||||
without="${without}esd,"
|
||||
use jack && with="${with}jackb," || without="${without}jackb,"
|
||||
use lame && with="${with}lame," || without="${without}lame,"
|
||||
use shout && with="${with}shout," || without="${without}shout,"
|
||||
use vorbis && with="${with}vorbis," || without="${without}vorbis,"
|
||||
|
||||
# move the original setup.cfg out of the way as a backup to check syntax
|
||||
mv setup.cfg setup.cfg.orig || die
|
||||
|
||||
# fill the setup.cfg with the values
|
||||
cat > setup.cfg <<-EOF
|
||||
[build_scripts]
|
||||
default_driver=${defdriver}
|
||||
[build_ext]
|
||||
with-drivers=${with}
|
||||
without-drivers=${without}
|
||||
intmath=$(use intmath && echo 1 || echo 0)
|
||||
EOF
|
||||
|
||||
mydistutilargs=( --default-driver ${defdriver} )
|
||||
}
|
||||
|
||||
python_install() {
|
||||
# a pyqt4 gui addon for boodler downloaded from the official site
|
||||
# http://boodler.org/dl/etc/boodle-ui-qt.py
|
||||
if use qt4 ; then
|
||||
python_doscript "${T}"/${EPYTHON}/boodle-ui-qt
|
||||
fi
|
||||
|
||||
distutils-r1_python_install
|
||||
}
|
||||
|
||||
src_install() {
|
||||
distutils-r1_src_install
|
||||
|
||||
# a bash completion addon script downloaded from the official site
|
||||
# http://boodler.org/dl/etc/bash_completion.d/boodler
|
||||
dobashcomp "${T}/boodler"
|
||||
}
|
@ -0,0 +1,316 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Boodler: a programmable soundscape tool
|
||||
# Designed by Andrew Plotkin <erkyrath@eblong.com>
|
||||
# For more information, see <http://boodler.org/>
|
||||
#
|
||||
# This Python script ("boodle-ui-qt.py") is licensed under the GNU
|
||||
# Library General Public License (LGPL).
|
||||
# Author: Tuukka Hastrup <Tuukka.Hastrup@iki.fi>
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public License
|
||||
# along with this program. (It should be a document entitled "LGPL".)
|
||||
# If not, see the web URL above, or write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import os, signal
|
||||
|
||||
from boopak import collect # you'll need Boodler on Python's library path
|
||||
|
||||
# same as in boodler.py
|
||||
if 'darwin' in sys.platform.lower():
|
||||
Default_Relative_Data_Dir = 'Library/Application Support/Boodler'
|
||||
else:
|
||||
Default_Relative_Data_Dir = '.boodler'
|
||||
|
||||
basedir = None # XXX opts.basedir
|
||||
if not basedir:
|
||||
basedir = os.environ.get('BOODLER_DATA')
|
||||
if not basedir:
|
||||
basedir = os.path.join(os.environ.get('HOME'), Default_Relative_Data_Dir)
|
||||
|
||||
|
||||
# collect the list of agents
|
||||
|
||||
l = collect.PackageCollection(basedir=basedir)
|
||||
|
||||
pkgs = l.list_all_current_packages()
|
||||
|
||||
agents = []
|
||||
|
||||
for pkgname,_vers in sorted(pkgs):
|
||||
pkg = l.load(pkgname)
|
||||
for resname in sorted(pkg.resources.keys()):
|
||||
res = pkg.resources.get(resname)
|
||||
if res.get_one("boodler.use") == "agent":
|
||||
agents += [(pkgname, resname)]
|
||||
|
||||
|
||||
def play(agent):
|
||||
boodler = ["boodler.py", "%s/%s" % agent]
|
||||
return boodler
|
||||
|
||||
def textplay(agent):
|
||||
print "Playing %s/%s" % agent,
|
||||
|
||||
pkg = l.load(agent[0])
|
||||
res = pkg.resources.get(agent[1])
|
||||
print '"%s"' % res.get_one("dc.title"), "... ",
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
boodler = subprocess.Popen(play(agent), stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
try:
|
||||
boodler.communicate()
|
||||
if boodler.returncode == 0:
|
||||
print "Done."
|
||||
else:
|
||||
print "Boodler failed with exit code %s." % boodler.returncode
|
||||
except KeyboardInterrupt:
|
||||
print "\nInterrupted"
|
||||
os.kill(boodler.pid, signal.SIGTERM)
|
||||
try:
|
||||
boodler.wait()
|
||||
except KeyboardInterrupt:
|
||||
os.kill(boodler.pid, signal.SIGKILL)
|
||||
|
||||
def textmain():
|
||||
for agent in agents:
|
||||
textplay(agent)
|
||||
|
||||
def qtmain():
|
||||
from PyQt4 import QtCore, QtGui # you'll need PyQt4 (python-qt4)
|
||||
|
||||
def index2rowdata(index):
|
||||
rowdata = (index.sibling(index.row(), 0).data().toString(),
|
||||
index.sibling(index.row(), 1).data().toString(),
|
||||
index.sibling(index.row(), 2).data().toString(),
|
||||
)
|
||||
|
||||
return rowdata
|
||||
|
||||
class Window(QtGui.QWidget):
|
||||
def __init__(self, app):
|
||||
self.boodler = None
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
|
||||
self.connect(app, QtCore.SIGNAL('aboutToQuit()'), self.stopPlay)
|
||||
|
||||
# proxy model for sorting and filtering
|
||||
self.proxyModel = QtGui.QSortFilterProxyModel()
|
||||
self.proxyModel.setDynamicSortFilter(True)
|
||||
self.proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
self.proxyModel.setFilterKeyColumn(2)
|
||||
|
||||
# widgets for now playing agent
|
||||
self.nowPlayingGroupBox = QtGui.QGroupBox("Now playing")
|
||||
self.nowPlayingLabel = QtGui.QLabel("Double-click a soundscape to play\n")
|
||||
self.nowPlayingButton = QtGui.QPushButton(self.style().standardIcon(QtGui.QStyle.SP_MediaStop), "&Stop")
|
||||
self.nowPlayingButton.setEnabled(False)
|
||||
|
||||
# signals for now playing agent
|
||||
self.connect(self.nowPlayingButton, QtCore.SIGNAL('clicked()'), self.stopPlay)
|
||||
|
||||
# widgets for selected agent
|
||||
self.selectedGroupBox = QtGui.QGroupBox("Selected soundscape")
|
||||
self.selectedLabel = QtGui.QLabel("Click a soundscape to view details\n")
|
||||
self.selectedInfoLabel = QtGui.QLabel("Internal name:\nLicense:\nSource:")
|
||||
self.selectedButton = QtGui.QPushButton(self.style().standardIcon(QtGui.QStyle.SP_MediaPlay), "&Play")
|
||||
self.selectedButton.setEnabled(False)
|
||||
|
||||
# signals for now playing agent
|
||||
self.connect(self.selectedButton, QtCore.SIGNAL('clicked()'), self.playButtonClicked)
|
||||
|
||||
# view widgets
|
||||
self.proxyGroupBox = QtGui.QGroupBox("Available soundscapes")
|
||||
|
||||
self.proxyView = QtGui.QTreeView()
|
||||
self.proxyView.setRootIsDecorated(False)
|
||||
self.proxyView.setAlternatingRowColors(True)
|
||||
self.proxyView.setModel(self.proxyModel)
|
||||
self.proxyView.setSortingEnabled(True)
|
||||
self.proxyView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
|
||||
self.proxyView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
|
||||
self.proxyView.setAllColumnsShowFocus(True)
|
||||
|
||||
# filter pattern widgets
|
||||
self.filterPatternLineEdit = QtGui.QLineEdit()
|
||||
self.filterPatternLabel = QtGui.QLabel("F&ind:")
|
||||
self.filterPatternLabel.setBuddy(self.filterPatternLineEdit)
|
||||
|
||||
# filter pattern signals
|
||||
self.connect(self.filterPatternLineEdit,
|
||||
QtCore.SIGNAL('textChanged(const QString &)'),
|
||||
self.filterRegExpChanged)
|
||||
|
||||
self.connect(self.proxyView.selectionModel(),
|
||||
QtCore.SIGNAL('currentRowChanged(const QModelIndex &, const QModelIndex &)'),
|
||||
self.itemSelected)
|
||||
self.connect(self.proxyView, QtCore.SIGNAL('activated(const QModelIndex &)'), self.itemActivated)
|
||||
|
||||
# now playing layout
|
||||
nowPlayingLayout = QtGui.QHBoxLayout()
|
||||
nowPlayingLayout.addWidget(self.nowPlayingButton)
|
||||
nowPlayingLayout.addWidget(self.nowPlayingLabel, 1)
|
||||
self.nowPlayingGroupBox.setLayout(nowPlayingLayout)
|
||||
|
||||
# selected layout
|
||||
selectedLayout = QtGui.QVBoxLayout()
|
||||
selectedLayoutH = QtGui.QHBoxLayout()
|
||||
selectedLayoutH.addWidget(self.selectedButton)
|
||||
selectedLayoutH.addWidget(self.selectedLabel, 1)
|
||||
selectedLayout.addLayout(selectedLayoutH)
|
||||
selectedLayout.addWidget(self.selectedInfoLabel)
|
||||
self.selectedGroupBox.setLayout(selectedLayout)
|
||||
|
||||
# available agents layout
|
||||
filterPatternLayout = QtGui.QHBoxLayout()
|
||||
filterPatternLayout.addWidget(self.filterPatternLabel)
|
||||
filterPatternLayout.addWidget(self.filterPatternLineEdit)
|
||||
|
||||
proxyLayout = QtGui.QVBoxLayout()
|
||||
proxyLayout.addWidget(self.proxyView)
|
||||
proxyLayout.addLayout(filterPatternLayout)
|
||||
self.proxyGroupBox.setLayout(proxyLayout)
|
||||
|
||||
# main layout
|
||||
mainLayout = QtGui.QVBoxLayout()
|
||||
mainLayout.addWidget(self.nowPlayingGroupBox)
|
||||
mainLayout.addWidget(self.selectedGroupBox)
|
||||
mainLayout.addWidget(self.proxyGroupBox)
|
||||
self.setLayout(mainLayout)
|
||||
|
||||
# set top-level window properties
|
||||
self.setWindowTitle("Boodle UI")
|
||||
self.resize(500, 450)
|
||||
|
||||
# set initial state
|
||||
self.proxyView.sortByColumn(2, QtCore.Qt.AscendingOrder)
|
||||
self.filterPatternLineEdit.setText("")
|
||||
|
||||
def setSourceModel(self, model):
|
||||
self.proxyModel.setSourceModel(model)
|
||||
|
||||
def filterRegExpChanged(self):
|
||||
regExp = QtCore.QRegExp(self.filterPatternLineEdit.text(), QtCore.Qt.CaseInsensitive, QtCore.QRegExp.Wildcard)
|
||||
self.proxyModel.setFilterRegExp(regExp)
|
||||
|
||||
def itemSelected(self, currentIndex, _previousIndex):
|
||||
if not currentIndex.isValid():
|
||||
return # keep the latest selection, if any
|
||||
row = index2rowdata(currentIndex)
|
||||
self.lastSelectedRow = row
|
||||
self.selectedButton.setEnabled(True)
|
||||
self.updateSelected(row)
|
||||
|
||||
def itemActivated(self, index):
|
||||
row = index2rowdata(index)
|
||||
self.startPlay((str(row[0]), str(row[1])))
|
||||
self.updateNowPlaying(row)
|
||||
|
||||
def playButtonClicked(self):
|
||||
row = self.lastSelectedRow
|
||||
self.startPlay((str(row[0]), str(row[1])))
|
||||
self.updateNowPlaying(row)
|
||||
|
||||
def updateNowPlaying(self, row):
|
||||
pkg = l.load(str(row[0]))
|
||||
creator = pkg.metadata.get_one("dc.creator")
|
||||
pkgtitle = pkg.metadata.get_one("dc.title")
|
||||
|
||||
msg = '"%s"\nby %s from "%s"' % (row[2], creator, pkgtitle)
|
||||
self.nowPlayingLabel.setText(msg)
|
||||
|
||||
def updateSelected(self, row):
|
||||
pkg = l.load(str(row[0]))
|
||||
creator = pkg.metadata.get_one("dc.creator")
|
||||
pkgtitle = pkg.metadata.get_one("dc.title")
|
||||
license = pkg.metadata.get_one("dc.license")
|
||||
source = pkg.metadata.get_one("dc.source")
|
||||
|
||||
msg = '"%s"\nby %s from "%s"' % (row[2], creator, pkgtitle)
|
||||
self.selectedLabel.setText(msg)
|
||||
|
||||
info = 'Internal name: %s/%s' % (row[0], row[1])
|
||||
info += '\nLicense: %s' % license
|
||||
info += '\nSource: %s' % source
|
||||
self.selectedInfoLabel.setText(info)
|
||||
|
||||
def startPlay(self, agent):
|
||||
self.stopPlay()
|
||||
|
||||
self.boodler = QtCore.QProcess(self)
|
||||
self.connect(self.boodler, QtCore.SIGNAL('error(QProcess::ProcessError)'), self.playError)
|
||||
self.connect(self.boodler, QtCore.SIGNAL('finished(int,QProcess::ExitStatus)'), self.playFinished)
|
||||
|
||||
cmd = play(agent)
|
||||
print "Launching: %s" % ' '.join(cmd)
|
||||
self.boodler.start(cmd[0], cmd[1:])
|
||||
|
||||
self.nowPlayingButton.setEnabled(True)
|
||||
|
||||
def stopPlay(self):
|
||||
if self.boodler:
|
||||
self.disconnect(self.boodler, QtCore.SIGNAL('error(QProcess::ProcessError)'), self.playError)
|
||||
self.disconnect(self.boodler, QtCore.SIGNAL('finished(int, QProcess::ExitStatus)'), self.playFinished)
|
||||
if self.boodler.state() != QtCore.QProcess.NotRunning:
|
||||
self.boodler.terminate()
|
||||
if not self.boodler.waitForFinished(5000):
|
||||
self.boodler.kill()
|
||||
self.boodler = None
|
||||
|
||||
self.nowPlayingButton.setEnabled(False)
|
||||
|
||||
def playError(self, error):
|
||||
if error == QtCore.QProcess.FailedToStart:
|
||||
print "Boodler failed to start: %s" % self.boodler.errorString()
|
||||
elif error == QtCore.QProcess.Crashed:
|
||||
print "Boodler crashed with exit code %s." % self.boodler.exitCode()
|
||||
else:
|
||||
print "Boodler failed with error %s." % error
|
||||
|
||||
self.stopPlay()
|
||||
|
||||
def playFinished(self, exitCode, exitStatus):
|
||||
if exitCode != 0:
|
||||
print self.boodler.readAllStandardError()
|
||||
print "Boodler failed with exit code %s." % exitCode
|
||||
else:
|
||||
print "Boodler done playing."
|
||||
|
||||
self.stopPlay()
|
||||
|
||||
def createAgentModel(parent):
|
||||
model = QtGui.QStandardItemModel(0, 3, parent)
|
||||
|
||||
model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Package"))
|
||||
model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("Resource"))
|
||||
model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Title"))
|
||||
|
||||
def standardItem(x):
|
||||
if x is None:
|
||||
return QtGui.QStandardItem("")
|
||||
else:
|
||||
return QtGui.QStandardItem(x)
|
||||
|
||||
for agent in reversed(agents):
|
||||
pkg = l.load(agent[0])
|
||||
res = pkg.resources.get(agent[1])
|
||||
title = res.get_one("dc.title")
|
||||
model.appendRow(map(standardItem, [agent[0], agent[1], title]))
|
||||
|
||||
return model
|
||||
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
window = Window(app)
|
||||
window.setSourceModel(createAgentModel(window))
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
qtmain()
|
@ -0,0 +1,86 @@
|
||||
# /etc/bash_completion.d/boodler #v3
|
||||
mgr=boodle-mgr.py
|
||||
|
||||
#types="agent" # only agents
|
||||
types="agent\|sound" #
|
||||
|
||||
typefilter=".*\[\(${types}\)\].*"
|
||||
|
||||
|
||||
#20091113 - v3 - typefilter introduction
|
||||
#20091113 - v2 - cleanup, documentation, bugfix, substring version
|
||||
#20091113 - v1 - initial working version
|
||||
|
||||
# does simple bash completion for boodler.py in via wildcard or a two-step process
|
||||
# type
|
||||
# boodler.py <tab><tab> # to get package completion
|
||||
# boodler.py name.me.example/<tab><tab> # for agent completion
|
||||
# boodler.py exam*<tab><tab> # get substring matching completion
|
||||
|
||||
|
||||
_boodlelib()
|
||||
{
|
||||
# case insensitive matches
|
||||
if `shopt -q nocasematch`; then
|
||||
oldnocasematchset=true ; else oldnocasematchset=false ;
|
||||
fi
|
||||
shopt -s nocasematch # FIXME - TRAP ME
|
||||
|
||||
local cur prev opts
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
# packages list (have to remove the last line 'xx packages installed...')
|
||||
packages=`$mgr -- list 2>/dev/null | sed "$ s/.*//"`
|
||||
|
||||
|
||||
case "$cur" in
|
||||
*\*) # WILDCARD - long, thorough search (package/agent completion)
|
||||
cur="${cur%\*}" # removing the wildcard
|
||||
agents=""
|
||||
for p in $packages; do
|
||||
ags=`$mgr contents "$p" 2>/dev/null | grep -e "${typefilter}" | awk '{print $1}'`
|
||||
#echo ags_${ags}_ags
|
||||
for ag in $ags; do
|
||||
pag="$p/$ag"
|
||||
if [[ "$pag" == *${cur}* ]] ; then
|
||||
#echo "$pag" == *${cur}*
|
||||
|
||||
agents+="$pag "
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
COMPREPLY=( ${agents} )
|
||||
;;
|
||||
*/*) # AGENT completion
|
||||
p="${cur%\/}" # removing the trailing slash
|
||||
|
||||
ags=`$mgr contents "$p" 2>/dev/null | grep -e "${typefilter}" | awk '{print $1}'`
|
||||
for ag in $ags; do
|
||||
# echo found $ag
|
||||
agents+="$p/$ag "
|
||||
done
|
||||
|
||||
opts="$agents"
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
;;
|
||||
*) # PACKAGE completion
|
||||
# match first on packages (with slashes at the end)
|
||||
opts=`echo "$packages" | sed "s/\([a-zA-Z0-9]\)$/\1\//"`
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
;;
|
||||
esac
|
||||
|
||||
# clean-up
|
||||
if ${oldnocasematchset} ; then
|
||||
shopt -s nocasematch
|
||||
else
|
||||
shopt -u nocasematch
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -o nospace -F _boodlelib boodler.py
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
|
||||
<pkgmetadata>
|
||||
<maintainer type="person">
|
||||
<email>webmaster@gentoostudio.org</email>
|
||||
<name>Gentoo Studio/Damien Moody</name>
|
||||
</maintainer>
|
||||
<use>
|
||||
<flag name="intmath">reduces the number of floating-point operations at the cost of less accurate volume fading</flag>
|
||||
<flag name="shout">Enable shoutcast support</flag>
|
||||
</use>
|
||||
</pkgmetadata>
|
Loading…
Reference in new issue