/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.27.16 by Martin von Gagern
Added distutils setup script and plugin meta data.
1
#!/usr/bin/env python
0.27.2 by Martin von Gagern
First programmatic generation of completions.
2
5147.5.4 by Martin von Gagern
Assign copyright to Canonical Ltd.
3
# Copyright (C) 2009, 2010 Canonical Ltd
0.27.14 by Martin von Gagern
Added GPL 2 license document and copyright notice.
4
#
5147.5.5 by Martin von Gagern
Adjust copyright notice comments for bash_completion.
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
0.27.14 by Martin von Gagern
Added GPL 2 license document and copyright notice.
14
#
15
# You should have received a copy of the GNU General Public License
5147.5.5 by Martin von Gagern
Adjust copyright notice comments for bash_completion.
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.27.14 by Martin von Gagern
Added GPL 2 license document and copyright notice.
18
0.28.2 by Martin von Gagern
merge from trunk
19
from bzrlib import (
5245.1.1 by Andrew Bennetts
Fix deprecation warning in bash_completion plugin.
20
    cmdline,
0.28.2 by Martin von Gagern
merge from trunk
21
    commands,
22
    config,
23
    help_topics,
24
    option,
25
    plugin,
26
)
0.27.36 by Martin von Gagern
List versions of bzr and plugins.
27
import bzrlib
0.27.18 by Martin von Gagern
Add global options in all cases
28
import re
0.27.2 by Martin von Gagern
First programmatic generation of completions.
29
0.32.8 by Martin von Gagern
Refactor to increase modularity.
30
31
class BashCodeGen(object):
32
    """Generate a bash script for given completion data."""
33
34
    def __init__(self, data, function_name='_bzr', debug=False):
35
        self.data = data
36
        self.function_name = function_name
37
        self.debug = debug
38
39
    def script(self):
40
        return ("""\
0.30.3 by Martin von Gagern
Lazy initialization
41
# Programmable completion for the Bazaar-NG bzr command under bash.
42
# Known to work with bash 2.05a as well as bash 4.1.2, and probably
43
# all versions in between as well.
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
44
45
# Based originally on the svn bash completition script.
46
# Customized by Sven Wilhelm/Icecrash.com
0.27.2 by Martin von Gagern
First programmatic generation of completions.
47
# Adjusted for automatic generation by Martin von Gagern
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
48
5147.5.12 by Martin von Gagern
Use version of bzrlib. Drop meta.py.
49
# Generated using the bash_completion plugin.
0.27.17 by Martin von Gagern
Mention version and homepage in generated shell code comment.
50
# See https://launchpad.net/bzr-bash-completion for details.
51
0.27.36 by Martin von Gagern
List versions of bzr and plugins.
52
# Commands and options of bzr %(bzr_version)s
53
0.27.20 by Martin von Gagern
More flexible handling of fixed word lists.
54
shopt -s progcomp
0.32.8 by Martin von Gagern
Refactor to increase modularity.
55
%(function)s
56
complete -F %(function_name)s -o default bzr
57
"""     % {
58
            "function_name": self.function_name,
59
            "function": self.function(),
60
            "bzr_version": self.bzr_version(),
61
        })
62
63
    def function(self):
64
        return ("""\
0.27.4 by Martin von Gagern
Introduce --function-name switch. (LP #439829)
65
%(function_name)s ()
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
66
{
0.27.20 by Martin von Gagern
More flexible handling of fixed word lists.
67
	local cur cmds cmdIdx cmd cmdOpts fixedWords i globalOpts
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
68
	local curOpt optEnums
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
69
70
	COMPREPLY=()
71
	cur=${COMP_WORDS[COMP_CWORD]}
72
0.27.2 by Martin von Gagern
First programmatic generation of completions.
73
	cmds='%(cmds)s'
0.27.19 by Martin von Gagern
Take global options preceding the command into account.
74
	globalOpts='%(global_options)s'
75
76
	# do ordinary expansion if we are anywhere after a -- argument
77
	for ((i = 1; i < COMP_CWORD; ++i)); do
78
		[[ ${COMP_WORDS[i]} == "--" ]] && return 0
79
	done
80
81
	# find the command; it's the first word not starting in -
82
	cmd=
83
	for ((cmdIdx = 1; cmdIdx < ${#COMP_WORDS[@]}; ++cmdIdx)); do
84
		if [[ ${COMP_WORDS[cmdIdx]} != -* ]]; then
85
			cmd=${COMP_WORDS[cmdIdx]}
86
			break
87
		fi
88
	done
89
90
	# complete command name if we are not already past the command
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
91
	if [[ $COMP_CWORD -le cmdIdx ]]; then
0.27.18 by Martin von Gagern
Add global options in all cases
92
		COMPREPLY=( $( compgen -W "$cmds $globalOpts" -- $cur ) )
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
93
		return 0
94
	fi
95
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
96
	# find the option for which we want to complete a value
97
	curOpt=
98
	if [[ $cur != -* ]] && [[ $COMP_CWORD -gt 1 ]]; then
99
		curOpt=${COMP_WORDS[COMP_CWORD - 1]}
100
		if [[ $curOpt == = ]]; then
101
			curOpt=${COMP_WORDS[COMP_CWORD - 2]}
0.32.1 by Martin von Gagern
Complete tag names.
102
		elif [[ $cur == : ]]; then
103
			cur=
104
			curOpt="$curOpt:"
105
		elif [[ $curOpt == : ]]; then
106
			curOpt=${COMP_WORDS[COMP_CWORD - 2]}:
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
107
		fi
108
	fi
0.27.31 by Martin von Gagern
Introduce --debug switch to enable some debugging code.
109
%(debug)s
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
110
	cmdOpts=
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
111
	optEnums=
0.27.20 by Martin von Gagern
More flexible handling of fixed word lists.
112
	fixedWords=
0.27.19 by Martin von Gagern
Take global options preceding the command into account.
113
	case $cmd in
0.27.2 by Martin von Gagern
First programmatic generation of completions.
114
%(cases)s\
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
115
	*)
0.27.2 by Martin von Gagern
First programmatic generation of completions.
116
		cmdOpts='--help -h'
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
117
		;;
118
	esac
119
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
120
	if [[ -z $fixedWords ]] && [[ -z $optEnums ]] && [[ $cur != -* ]]; then
0.32.1 by Martin von Gagern
Complete tag names.
121
		case $curOpt in
122
			tag:*)
0.32.7 by Martin von Gagern
Allow different formats for tag completion.
123
				fixedWords="$(bzr tags 2>/dev/null | sed 's/  *[^ ]*$//')"
0.32.1 by Martin von Gagern
Complete tag names.
124
				;;
125
		esac
126
	elif [[ $cur == = ]] && [[ -n $optEnums ]]; then
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
127
		# complete directly after "--option=", list all enum values
0.32.3 by Martin von Gagern
Restore completion of registry options immediately after =.
128
		COMPREPLY=( $optEnums )
129
		return 0
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
130
	else
131
		fixedWords="$cmdOpts $globalOpts $optEnums $fixedWords"
0.32.1 by Martin von Gagern
Complete tag names.
132
	fi
133
134
	if [[ -n $fixedWords ]]; then
0.27.30 by Martin von Gagern
Complete values for enum_switch of RegistryOptions.
135
		COMPREPLY=( $( compgen -W "$fixedWords" -- $cur ) )
136
	fi
0.27.1 by Martin von Gagern
Original script from bzr.dev/contrib/bash/bzr
137
138
	return 0
139
}
0.32.8 by Martin von Gagern
Refactor to increase modularity.
140
"""     % {
141
            "cmds": self.command_names(),
142
            "function_name": self.function_name,
143
            "cases": self.command_cases(),
144
            "global_options": self.global_options(),
145
            "debug": self.debug_output(),
146
        })
147
148
    def command_names(self):
149
        return " ".join(self.data.all_command_aliases())
150
151
    def debug_output(self):
152
        if not self.debug:
153
            return ''
154
        else:
155
            return (r"""
0.27.31 by Martin von Gagern
Introduce --debug switch to enable some debugging code.
156
	# Debugging code enabled using the --debug command line switch.
157
	# Will dump some variables to the top portion of the terminal.
158
	echo -ne '\e[s\e[H'
159
	for (( i=0; i < ${#COMP_WORDS[@]}; ++i)); do
160
		echo "\$COMP_WORDS[$i]='${COMP_WORDS[i]}'"$'\e[K'
161
	done
162
	for i in COMP_CWORD COMP_LINE COMP_POINT COMP_TYPE COMP_KEY cur curOpt; do
163
		echo "\$${i}=\"${!i}\""$'\e[K'
164
	done
165
	echo -ne '---\e[K\e[u'
0.32.8 by Martin von Gagern
Refactor to increase modularity.
166
""")
167
168
    def bzr_version(self):
169
        bzr_version = bzrlib.version_string
170
        if not self.data.plugins:
171
            bzr_version += "."
172
        else:
173
            bzr_version += " and the following plugins:"
174
            for name, plugin in sorted(self.data.plugins.iteritems()):
175
                bzr_version += "\n# %s" % plugin
0.32.9 by Martin von Gagern
Added test cases for DataCollector and BashCodeGen.
176
        return bzr_version
0.32.8 by Martin von Gagern
Refactor to increase modularity.
177
178
    def global_options(self):
179
        return " ".join(sorted(self.data.global_options))
180
181
    def command_cases(self):
182
        cases = ""
183
        for command in self.data.commands:
184
            cases += self.command_case(command)
185
        return cases
186
187
    def command_case(self, command):
188
        case = "\t%s)\n" % "|".join(command.aliases)
189
        if command.plugin:
190
            case += "\t\t# plugin \"%s\"\n" % command.plugin
191
        options = []
192
        enums = []
193
        for option in command.options:
194
            for message in option.error_messages:
195
                case += "\t\t# %s\n" % message
196
            if option.registry_keys:
197
                for key in option.registry_keys:
198
                    options.append("%s=%s" % (option, key))
199
                enums.append("%s) optEnums='%s' ;;" %
200
                             (option, ' '.join(option.registry_keys)))
201
            else:
202
                options.append(str(option))
203
        case += "\t\tcmdOpts='%s'\n" % " ".join(options)
204
        if command.fixed_words:
205
            fixed_words = command.fixed_words
206
            if isinstance(fixed_words, list):
207
                fixed_words = "'%s'" + ' '.join(fixed_words)
208
            case += "\t\tfixedWords=%s\n" % fixed_words
209
        if enums:
210
            case += "\t\tcase $curOpt in\n\t\t\t"
211
            case += "\n\t\t\t".join(enums)
212
            case += "\n\t\tesac\n"
213
        case += "\t\t;;\n"
214
        return case
215
216
217
class CompletionData(object):
218
219
    def __init__(self):
220
        self.plugins = {}
221
        self.global_options = set()
222
        self.commands = []
223
224
    def all_command_aliases(self):
225
        for c in self.commands:
226
            for a in c.aliases:
227
                yield a
228
229
230
class CommandData(object):
231
232
    def __init__(self, name):
233
        self.name = name
234
        self.aliases = [name]
235
        self.plugin = None
236
        self.options = []
237
        self.fixed_words = None
238
239
240
class PluginData(object):
241
242
    def __init__(self, name, version=None):
243
        if version is None:
244
            version = bzrlib.plugin.plugins()[name].__version__
245
        self.name = name
246
        self.version = version
247
248
    def __str__(self):
249
        if self.version == 'unknown':
250
            return self.name
251
        return '%s %s' % (self.name, self.version)
252
253
254
class OptionData(object):
255
256
    def __init__(self, name):
257
        self.name = name
258
        self.registry_keys = None
259
        self.error_messages = []
260
261
    def __str__(self):
262
        return self.name
263
264
    def __cmp__(self, other):
265
        return cmp(self.name, other.name)
266
267
268
class DataCollector(object):
269
270
    def __init__(self, no_plugins=False, selected_plugins=None):
271
        self.data = CompletionData()
272
        self.user_aliases = {}
273
        if no_plugins:
274
            self.selected_plugins = set()
275
        elif selected_plugins is None:
276
            self.selected_plugins = None
277
        else:
278
            self.selected_plugins = set([x.replace('-', '_')
279
                                         for x in selected_plugins])
280
281
    def collect(self):
282
        self.global_options()
283
        self.aliases()
284
        self.commands()
285
        return self.data
286
287
    def global_options(self):
288
        re_switch = re.compile(r'\n(--[A-Za-z0-9-_]+)(?:, (-\S))?\s')
289
        help_text = help_topics.topic_registry.get_detail('global-options')
290
        for long, short in re_switch.findall(help_text):
291
            self.data.global_options.add(long)
292
            if short:
293
                self.data.global_options.add(short)
294
295
    def aliases(self):
296
        for alias, expansion in config.GlobalConfig().get_aliases().iteritems():
5245.1.1 by Andrew Bennetts
Fix deprecation warning in bash_completion plugin.
297
            for token in cmdline.split(expansion):
0.32.8 by Martin von Gagern
Refactor to increase modularity.
298
                if not token.startswith("-"):
299
                    self.user_aliases.setdefault(token, set()).add(alias)
300
                    break
301
302
    def commands(self):
303
        for name in sorted(commands.all_command_names()):
304
            self.command(name)
305
306
    def command(self, name):
307
        cmd = commands.get_cmd_object(name)
308
        cmd_data = CommandData(name)
309
310
        plugin_name = cmd.plugin_name()
311
        if plugin_name is not None:
312
            if (self.selected_plugins is not None and
313
                plugin not in self.selected_plugins):
0.32.9 by Martin von Gagern
Added test cases for DataCollector and BashCodeGen.
314
                return None
0.32.8 by Martin von Gagern
Refactor to increase modularity.
315
            plugin_data = self.data.plugins.get(plugin_name)
316
            if plugin_data is None:
317
                plugin_data = PluginData(plugin_name)
318
                self.data.plugins[plugin_name] = plugin_data
319
            cmd_data.plugin = plugin_data
320
        self.data.commands.append(cmd_data)
0.27.12 by Martin von Gagern
Take user-configured aliases into account.
321
322
        # Find all aliases to the command; both cmd-defined and user-defined.
323
        # We assume a user won't override one command with a different one,
324
        # but will choose completely new names or add options to existing
325
        # ones while maintaining the actual command name unchanged.
0.32.8 by Martin von Gagern
Refactor to increase modularity.
326
        cmd_data.aliases.extend(cmd.aliases)
327
        cmd_data.aliases.extend(sorted([useralias
328
            for cmdalias in cmd_data.aliases
329
            if cmdalias in self.user_aliases
330
            for useralias in self.user_aliases[cmdalias]
331
            if useralias not in cmd_data.aliases]))
332
0.27.2 by Martin von Gagern
First programmatic generation of completions.
333
        opts = cmd.options()
0.32.8 by Martin von Gagern
Refactor to increase modularity.
334
        for optname, opt in sorted(opts.iteritems()):
335
            cmd_data.options.extend(self.option(opt))
336
337
        if 'help' == name or 'help' in cmd.aliases:
338
            cmd_data.fixed_words = ('"$cmds %s"' %
339
                " ".join(sorted(help_topics.topic_registry.keys())))
340
0.32.9 by Martin von Gagern
Added test cases for DataCollector and BashCodeGen.
341
        return cmd_data
342
0.32.8 by Martin von Gagern
Refactor to increase modularity.
343
    def option(self, opt):
344
        optswitches = {}
345
        parser = option.get_optparser({opt.name: opt})
346
        parser = self.wrap_parser(optswitches, parser)
347
        optswitches.clear()
348
        opt.add_option(parser, opt.short_name())
349
        if isinstance(opt, option.RegistryOption) and opt.enum_switch:
350
            enum_switch = '--%s' % opt.name
351
            enum_data = optswitches.get(enum_switch)
352
            if enum_data:
0.27.41 by Martin von Gagern
Recover from ImportError when loading a registry.
353
                try:
0.32.8 by Martin von Gagern
Refactor to increase modularity.
354
                    enum_data.registry_keys = opt.registry.keys()
0.27.41 by Martin von Gagern
Recover from ImportError when loading a registry.
355
                except ImportError, e:
0.32.8 by Martin von Gagern
Refactor to increase modularity.
356
                    enum_data.error_messages.append(
357
                        "ERROR getting registry keys for '--%s': %s"
358
                        % (opt.name, str(e).split('\n')[0]))
359
        return sorted(optswitches.values())
360
361
    def wrap_container(self, optswitches, parser):
362
        def tweaked_add_option(*opts, **attrs):
363
            for name in opts:
364
                optswitches[name] = OptionData(name)
365
        parser.add_option = tweaked_add_option
366
        return parser
367
368
    def wrap_parser(self, optswitches, parser):
369
        orig_add_option_group = parser.add_option_group
370
        def tweaked_add_option_group(*opts, **attrs):
371
            return self.wrap_container(optswitches,
372
                orig_add_option_group(*opts, **attrs))
373
        parser.add_option_group = tweaked_add_option_group
374
        return self.wrap_container(optswitches, parser)
375
376
377
def bash_completion_function(out, function_name="_bzr", function_only=False,
378
                             debug=False,
379
                             no_plugins=False, selected_plugins=None):
380
    dc = DataCollector(no_plugins=no_plugins, selected_plugins=selected_plugins)
381
    data = dc.collect()
382
    cg = BashCodeGen(data, function_name=function_name, debug=debug)
0.27.7 by Martin von Gagern
Introduce --function-only option
383
    if function_only:
0.32.8 by Martin von Gagern
Refactor to increase modularity.
384
        res = cg.function()
385
    else:
386
        res = cg.script()
387
    out.write(res)
388
0.27.2 by Martin von Gagern
First programmatic generation of completions.
389
5147.5.11 by Martin von Gagern
Register command lazily.
390
class cmd_bash_completion(commands.Command):
5147.5.14 by Martin von Gagern
Assign user-visible docstrings to __doc__.
391
    __doc__ = """Generate a shell function for bash command line completion.
5147.5.11 by Martin von Gagern
Register command lazily.
392
393
    This command generates a shell function which can be used by bash to
394
    automatically complete the currently typed command when the user presses
395
    the completion key (usually tab).
396
    
397
    Commonly used like this:
398
        eval "`bzr bash-completion`"
399
    """
400
401
    takes_options = [
402
        option.Option("function-name", short_name="f", type=str, argname="name",
403
               help="Name of the generated function (default: _bzr)"),
404
        option.Option("function-only", short_name="o", type=None,
405
               help="Generate only the shell function, don't enable it"),
406
        option.Option("debug", type=None, hidden=True,
407
               help="Enable shell code useful for debugging"),
408
        option.ListOption("plugin", type=str, argname="name",
409
                # param_name="selected_plugins", # doesn't work, bug #387117
410
                help="Enable completions for the selected plugin"
411
                + " (default: all plugins)"),
412
        ]
413
414
    def run(self, **kwargs):
415
        import sys
416
        from bashcomp import bash_completion_function
417
        if 'plugin' in kwargs:
418
            # work around bug #387117 which prevents us from using param_name
5147.5.18 by Martin von Gagern
Include all plugins if --plugins isn't specified (fixes regression).
419
            if len(kwargs['plugin']) > 0:
420
                kwargs['selected_plugins'] = kwargs['plugin']
5147.5.11 by Martin von Gagern
Register command lazily.
421
            del kwargs['plugin']
422
        bash_completion_function(sys.stdout, **kwargs)
423
424
0.27.2 by Martin von Gagern
First programmatic generation of completions.
425
if __name__ == '__main__':
426
427
    import sys
428
    import locale
0.27.32 by Martin von Gagern
Added OptionParser for script usage.
429
    import optparse
430
0.27.38 by Martin von Gagern
Add --plugin switch to selectively include plugins.
431
    def plugin_callback(option, opt, value, parser):
432
        values = parser.values.selected_plugins
433
        if value == '-':
434
            del values[:]
435
        else:
436
            values.append(value)
437
5147.5.12 by Martin von Gagern
Use version of bzrlib. Drop meta.py.
438
    parser = optparse.OptionParser(usage="%prog [-f NAME] [-o]")
0.27.32 by Martin von Gagern
Added OptionParser for script usage.
439
    parser.add_option("--function-name", "-f", metavar="NAME",
440
                      help="Name of the generated function (default: _bzr)")
441
    parser.add_option("--function-only", "-o", action="store_true",
442
                      help="Generate only the shell function, don't enable it")
443
    parser.add_option("--debug", action="store_true",
444
                      help=optparse.SUPPRESS_HELP)
0.27.37 by Martin von Gagern
Introduce --no-plugins option to script execution mode.
445
    parser.add_option("--no-plugins", action="store_true",
446
                      help="Don't load any bzr plugins")
0.27.38 by Martin von Gagern
Add --plugin switch to selectively include plugins.
447
    parser.add_option("--plugin", metavar="NAME", type="string",
448
                      dest="selected_plugins", default=[],
449
                      action="callback", callback=plugin_callback,
450
                      help="Enable completions for the selected plugin"
451
                      + " (default: all plugins)")
0.27.32 by Martin von Gagern
Added OptionParser for script usage.
452
    (opts, args) = parser.parse_args()
453
    if args:
454
        parser.error("script does not take positional arguments")
455
    kwargs = dict()
456
    for name, value in opts.__dict__.iteritems():
457
        if value is not None:
458
            kwargs[name] = value
0.27.2 by Martin von Gagern
First programmatic generation of completions.
459
460
    locale.setlocale(locale.LC_ALL, '')
0.27.37 by Martin von Gagern
Introduce --no-plugins option to script execution mode.
461
    if not kwargs.get('no_plugins', False):
462
        plugin.load_plugins()
0.27.2 by Martin von Gagern
First programmatic generation of completions.
463
    commands.install_bzr_command_hooks()
0.27.32 by Martin von Gagern
Added OptionParser for script usage.
464
    bash_completion_function(sys.stdout, **kwargs)