From efca307f7116d0b323b2aaf3c745a6da7f40eaac Mon Sep 17 00:00:00 2001 From: Niels Thykier Date: Sat, 22 Oct 2011 13:42:14 +0200 Subject: [PATCH] Added package completion to the readline completor --- britney.py | 52 ++++++++++++++++++++++++++++++++++++++++++++ completer.py | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 completer.py diff --git a/britney.py b/britney.py index 83991ea..71cdc54 100755 --- a/britney.py +++ b/britney.py @@ -2439,6 +2439,53 @@ class Britney: self.output_write("\nNewly uninstallable packages in testing:\n%s" % \ (text)) + def generate_package_list(self): + # list of local methods and variables (for better performance) + sources = self.sources + architectures = self.options.architectures + should_remove_source = self.should_remove_source + should_upgrade_srcarch = self.should_upgrade_srcarch + should_upgrade_src = self.should_upgrade_src + + # this list will contain the packages which are valid candidates; + # if a package is going to be removed, it will have a "-" prefix + upgrade_me = [] + + # for every source package in testing, check if it should be removed + for pkg in sources['testing']: + if should_remove_source(pkg): + upgrade_me.append("-" + pkg) + + # for every source package in unstable check if it should be upgraded + for pkg in sources['unstable']: + if sources['unstable'][pkg][FAKESRC]: continue + # if the source package is already present in testing, + # check if it should be upgraded for every binary package + if pkg in sources['testing'] and not sources['testing'][pkg][FAKESRC]: + for arch in architectures: + if should_upgrade_srcarch(pkg, arch, 'unstable'): + upgrade_me.append("%s/%s/%s" % (pkg, arch, sources['unstable'][pkg][VERSION])) + + # check if the source package should be upgraded + if should_upgrade_src(pkg, 'unstable'): + upgrade_me.append("%s/%s" % (pkg, sources['unstable'][pkg][VERSION])) + + # for every source package in *-proposed-updates, check if it should be upgraded + for suite in ['pu', 'tpu']: + for pkg in sources[suite]: + # if the source package is already present in testing, + # check if it should be upgraded for every binary package + if pkg in sources['testing']: + for arch in architectures: + if should_upgrade_srcarch(pkg, arch, suite): + upgrade_me.append("%s/%s_%s" % (pkg, arch, suite)) + + # check if the source package should be upgraded + if should_upgrade_src(pkg, suite): + upgrade_me.append("%s_%s" % (pkg, suite)) + + return upgrade_me + def hint_tester(self): """Run a command line interface to test hints @@ -2450,10 +2497,15 @@ class Britney: self.nuninst_orig_save = self.get_nuninst() import readline + from completer import Completer + histfile = os.path.expanduser('~/.britney2_history') if os.path.exists(histfile): readline.read_history_file(histfile) + readline.parse_and_bind('tab: complete') + readline.set_completer(Completer(self).completer) + while True: # read the command from the command line try: diff --git a/completer.py b/completer.py new file mode 100644 index 0000000..fc106f6 --- /dev/null +++ b/completer.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2011 Niels Thykier + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +import readline +import bisect + +class Completer: + """Completer class + + This class provides a readline completer for the britney hint-tester + command-line interface. + """ + + def __init__(self, britney): + """Constructor + + Creates a completer for a given britney. + """ + self.matches = [] + self.cmds = ['easy', 'hint', 'force-hint', 'exit', 'quit'] + self.britney = britney + self.packages = sorted(britney.generate_package_list()) + + def completer(self, text, state): + """readline completer (see the readline API)""" + + origline = readline.get_line_buffer() + words = origline.split() + + if state < 1: + self.matches = [] + if len(words) < 1 or words[0] == text: + # complete a command + self.matches = [x for x in self.cmds if x.startswith(text)] + else: + # complete pkg/[arch/]version + start = bisect.bisect_left(self.packages, text) + while start < len(self.packages): + if not self.packages[start].startswith(text): + break + self.matches.append(self.packages[start]) + start += 1 + + if len(self.matches) > state: + return self.matches[state] + return None + + + +