/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/plugins/bash_completion/bashcomp.py

  • Committer: Marius Kruger
  • Date: 2010-07-10 21:28:56 UTC
  • mto: (5384.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5385.
  • Revision ID: marius.kruger@enerweb.co.za-20100710212856-uq4ji3go0u5se7hx
* Update documentation
* add NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python3
 
1
#!/usr/bin/env python
2
2
 
3
3
# Copyright (C) 2009, 2010 Canonical Ltd
4
4
#
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
 
from ... import (
 
19
from bzrlib import (
20
20
    cmdline,
21
21
    commands,
22
22
    config,
24
24
    option,
25
25
    plugin,
26
26
)
27
 
import breezy
 
27
import bzrlib
28
28
import re
29
 
import sys
30
29
 
31
30
 
32
31
class BashCodeGen(object):
33
32
    """Generate a bash script for given completion data."""
34
33
 
35
 
    def __init__(self, data, function_name='_brz', debug=False):
 
34
    def __init__(self, data, function_name='_bzr', debug=False):
36
35
        self.data = data
37
36
        self.function_name = function_name
38
37
        self.debug = debug
39
38
 
40
39
    def script(self):
41
40
        return ("""\
42
 
# Programmable completion for the Breezy brz command under bash.
 
41
# Programmable completion for the Bazaar-NG bzr command under bash.
43
42
# Known to work with bash 2.05a as well as bash 4.1.2, and probably
44
43
# all versions in between as well.
45
44
 
50
49
# Generated using the bash_completion plugin.
51
50
# See https://launchpad.net/bzr-bash-completion for details.
52
51
 
53
 
# Commands and options of brz %(brz_version)s
 
52
# Commands and options of bzr %(bzr_version)s
54
53
 
55
54
shopt -s progcomp
56
55
%(function)s
57
 
complete -F %(function_name)s -o default brz
58
 
""" % {
 
56
complete -F %(function_name)s -o default bzr
 
57
"""     % {
59
58
            "function_name": self.function_name,
60
59
            "function": self.function(),
61
 
            "brz_version": self.brz_version(),
 
60
            "bzr_version": self.bzr_version(),
62
61
        })
63
62
 
64
63
    def function(self):
65
64
        return ("""\
66
65
%(function_name)s ()
67
66
{
68
 
    local cur cmds cmdIdx cmd cmdOpts fixedWords i globalOpts
69
 
    local curOpt optEnums
70
 
    local IFS=$' \\n'
71
 
 
72
 
    COMPREPLY=()
73
 
    cur=${COMP_WORDS[COMP_CWORD]}
74
 
 
75
 
    cmds='%(cmds)s'
76
 
    globalOpts=( %(global_options)s )
77
 
 
78
 
    # do ordinary expansion if we are anywhere after a -- argument
79
 
    for ((i = 1; i < COMP_CWORD; ++i)); do
80
 
        [[ ${COMP_WORDS[i]} == "--" ]] && return 0
81
 
    done
82
 
 
83
 
    # find the command; it's the first word not starting in -
84
 
    cmd=
85
 
    for ((cmdIdx = 1; cmdIdx < ${#COMP_WORDS[@]}; ++cmdIdx)); do
86
 
        if [[ ${COMP_WORDS[cmdIdx]} != -* ]]; then
87
 
            cmd=${COMP_WORDS[cmdIdx]}
88
 
            break
89
 
        fi
90
 
    done
91
 
 
92
 
    # complete command name if we are not already past the command
93
 
    if [[ $COMP_CWORD -le cmdIdx ]]; then
94
 
        COMPREPLY=( $( compgen -W "$cmds ${globalOpts[*]}" -- $cur ) )
95
 
        return 0
96
 
    fi
97
 
 
98
 
    # find the option for which we want to complete a value
99
 
    curOpt=
100
 
    if [[ $cur != -* ]] && [[ $COMP_CWORD -gt 1 ]]; then
101
 
        curOpt=${COMP_WORDS[COMP_CWORD - 1]}
102
 
        if [[ $curOpt == = ]]; then
103
 
            curOpt=${COMP_WORDS[COMP_CWORD - 2]}
104
 
        elif [[ $cur == : ]]; then
105
 
            cur=
106
 
            curOpt="$curOpt:"
107
 
        elif [[ $curOpt == : ]]; then
108
 
            curOpt=${COMP_WORDS[COMP_CWORD - 2]}:
109
 
        fi
110
 
    fi
 
67
        local cur cmds cmdIdx cmd cmdOpts fixedWords i globalOpts
 
68
        local curOpt optEnums
 
69
        local IFS=$' \\n'
 
70
 
 
71
        COMPREPLY=()
 
72
        cur=${COMP_WORDS[COMP_CWORD]}
 
73
 
 
74
        cmds='%(cmds)s'
 
75
        globalOpts=( %(global_options)s )
 
76
 
 
77
        # do ordinary expansion if we are anywhere after a -- argument
 
78
        for ((i = 1; i < COMP_CWORD; ++i)); do
 
79
                [[ ${COMP_WORDS[i]} == "--" ]] && return 0
 
80
        done
 
81
 
 
82
        # find the command; it's the first word not starting in -
 
83
        cmd=
 
84
        for ((cmdIdx = 1; cmdIdx < ${#COMP_WORDS[@]}; ++cmdIdx)); do
 
85
                if [[ ${COMP_WORDS[cmdIdx]} != -* ]]; then
 
86
                        cmd=${COMP_WORDS[cmdIdx]}
 
87
                        break
 
88
                fi
 
89
        done
 
90
 
 
91
        # complete command name if we are not already past the command
 
92
        if [[ $COMP_CWORD -le cmdIdx ]]; then
 
93
                COMPREPLY=( $( compgen -W "$cmds ${globalOpts[*]}" -- $cur ) )
 
94
                return 0
 
95
        fi
 
96
 
 
97
        # find the option for which we want to complete a value
 
98
        curOpt=
 
99
        if [[ $cur != -* ]] && [[ $COMP_CWORD -gt 1 ]]; then
 
100
                curOpt=${COMP_WORDS[COMP_CWORD - 1]}
 
101
                if [[ $curOpt == = ]]; then
 
102
                        curOpt=${COMP_WORDS[COMP_CWORD - 2]}
 
103
                elif [[ $cur == : ]]; then
 
104
                        cur=
 
105
                        curOpt="$curOpt:"
 
106
                elif [[ $curOpt == : ]]; then
 
107
                        curOpt=${COMP_WORDS[COMP_CWORD - 2]}:
 
108
                fi
 
109
        fi
111
110
%(debug)s
112
 
    cmdOpts=( )
113
 
    optEnums=( )
114
 
    fixedWords=( )
115
 
    case $cmd in
 
111
        cmdOpts=( )
 
112
        optEnums=( )
 
113
        fixedWords=( )
 
114
        case $cmd in
116
115
%(cases)s\
117
 
    *)
118
 
        cmdOpts=(--help -h)
119
 
        ;;
120
 
    esac
121
 
 
122
 
    IFS=$'\\n'
123
 
    if [[ ${#fixedWords[@]} -eq 0 ]] && [[ ${#optEnums[@]} -eq 0 ]] && [[ $cur != -* ]]; then
124
 
        case $curOpt in
125
 
            tag:|*..tag:)
126
 
                fixedWords=( $(brz tags 2>/dev/null | sed 's/  *[^ ]*$//; s/ /\\\\\\\\ /g;') )
127
 
                ;;
128
 
        esac
129
 
        case $cur in
130
 
            [\\"\\']tag:*)
131
 
                fixedWords=( $(brz tags 2>/dev/null | sed 's/  *[^ ]*$//; s/^/tag:/') )
132
 
                ;;
133
 
            [\\"\\']*..tag:*)
134
 
                fixedWords=( $(brz tags 2>/dev/null | sed 's/  *[^ ]*$//') )
135
 
                fixedWords=( $(for i in "${fixedWords[@]}"; do echo "${cur%%..tag:*}..tag:${i}"; done) )
136
 
                ;;
137
 
        esac
138
 
    elif [[ $cur == = ]] && [[ ${#optEnums[@]} -gt 0 ]]; then
139
 
        # complete directly after "--option=", list all enum values
140
 
        COMPREPLY=( "${optEnums[@]}" )
141
 
        return 0
142
 
    else
143
 
        fixedWords=( "${cmdOpts[@]}"
144
 
                     "${globalOpts[@]}"
145
 
                     "${optEnums[@]}"
146
 
                     "${fixedWords[@]}" )
147
 
    fi
148
 
 
149
 
    if [[ ${#fixedWords[@]} -gt 0 ]]; then
150
 
        COMPREPLY=( $( compgen -W "${fixedWords[*]}" -- $cur ) )
151
 
    fi
152
 
 
153
 
    return 0
 
116
        *)
 
117
                cmdOpts=(--help -h)
 
118
                ;;
 
119
        esac
 
120
 
 
121
        IFS=$'\\n'
 
122
        if [[ ${#fixedWords[@]} -eq 0 ]] && [[ ${#optEnums[@]} -eq 0 ]] && [[ $cur != -* ]]; then
 
123
                case $curOpt in
 
124
                        tag:|*..tag:)
 
125
                                fixedWords=( $(bzr tags 2>/dev/null | sed 's/  *[^ ]*$//; s/ /\\\\\\\\ /g;') )
 
126
                                ;;
 
127
                esac
 
128
                case $cur in
 
129
                        [\\"\\']tag:*)
 
130
                                fixedWords=( $(bzr tags 2>/dev/null | sed 's/  *[^ ]*$//; s/^/tag:/') )
 
131
                                ;;
 
132
                        [\\"\\']*..tag:*)
 
133
                                fixedWords=( $(bzr tags 2>/dev/null | sed 's/  *[^ ]*$//') )
 
134
                                fixedWords=( $(for i in "${fixedWords[@]}"; do echo "${cur%%..tag:*}..tag:${i}"; done) )
 
135
                                ;;
 
136
                esac
 
137
        elif [[ $cur == = ]] && [[ ${#optEnums[@]} -gt 0 ]]; then
 
138
                # complete directly after "--option=", list all enum values
 
139
                COMPREPLY=( "${optEnums[@]}" )
 
140
                return 0
 
141
        else
 
142
                fixedWords=( "${cmdOpts[@]}"
 
143
                             "${globalOpts[@]}"
 
144
                             "${optEnums[@]}"
 
145
                             "${fixedWords[@]}" )
 
146
        fi
 
147
 
 
148
        if [[ ${#fixedWords[@]} -gt 0 ]]; then
 
149
                COMPREPLY=( $( compgen -W "${fixedWords[*]}" -- $cur ) )
 
150
        fi
 
151
 
 
152
        return 0
154
153
}
155
 
""" % {
 
154
"""     % {
156
155
            "cmds": self.command_names(),
157
156
            "function_name": self.function_name,
158
157
            "cases": self.command_cases(),
169
168
            return ''
170
169
        else:
171
170
            return (r"""
172
 
    # Debugging code enabled using the --debug command line switch.
173
 
    # Will dump some variables to the top portion of the terminal.
174
 
    echo -ne '\e[s\e[H'
175
 
    for (( i=0; i < ${#COMP_WORDS[@]}; ++i)); do
176
 
        echo "\$COMP_WORDS[$i]='${COMP_WORDS[i]}'"$'\e[K'
177
 
    done
178
 
    for i in COMP_CWORD COMP_LINE COMP_POINT COMP_TYPE COMP_KEY cur curOpt; do
179
 
        echo "\$${i}=\"${!i}\""$'\e[K'
180
 
    done
181
 
    echo -ne '---\e[K\e[u'
 
171
        # Debugging code enabled using the --debug command line switch.
 
172
        # Will dump some variables to the top portion of the terminal.
 
173
        echo -ne '\e[s\e[H'
 
174
        for (( i=0; i < ${#COMP_WORDS[@]}; ++i)); do
 
175
                echo "\$COMP_WORDS[$i]='${COMP_WORDS[i]}'"$'\e[K'
 
176
        done
 
177
        for i in COMP_CWORD COMP_LINE COMP_POINT COMP_TYPE COMP_KEY cur curOpt; do
 
178
                echo "\$${i}=\"${!i}\""$'\e[K'
 
179
        done
 
180
        echo -ne '---\e[K\e[u'
182
181
""")
183
182
 
184
 
    def brz_version(self):
185
 
        brz_version = breezy.version_string
 
183
    def bzr_version(self):
 
184
        bzr_version = bzrlib.version_string
186
185
        if not self.data.plugins:
187
 
            brz_version += "."
 
186
            bzr_version += "."
188
187
        else:
189
 
            brz_version += " and the following plugins:"
190
 
            for name, plugin in sorted(self.data.plugins.items()):
191
 
                brz_version += "\n# %s" % plugin
192
 
        return brz_version
 
188
            bzr_version += " and the following plugins:"
 
189
            for name, plugin in sorted(self.data.plugins.iteritems()):
 
190
                bzr_version += "\n# %s" % plugin
 
191
        return bzr_version
193
192
 
194
193
    def global_options(self):
195
194
        return " ".join(sorted(self.data.global_options))
258
257
    def __init__(self, name, version=None):
259
258
        if version is None:
260
259
            try:
261
 
                version = breezy.plugin.plugins()[name].__version__
 
260
                version = bzrlib.plugin.plugins()[name].__version__
262
261
            except:
263
262
                version = 'unknown'
264
263
        self.name = name
283
282
    def __cmp__(self, other):
284
283
        return cmp(self.name, other.name)
285
284
 
286
 
    def __lt__(self, other):
287
 
        return self.name < other.name
288
 
 
289
285
 
290
286
class DataCollector(object):
291
287
 
297
293
        elif selected_plugins is None:
298
294
            self.selected_plugins = None
299
295
        else:
300
 
            self.selected_plugins = {x.replace('-', '_')
301
 
                                     for x in selected_plugins}
 
296
            self.selected_plugins = set([x.replace('-', '_')
 
297
                                         for x in selected_plugins])
302
298
 
303
299
    def collect(self):
304
300
        self.global_options()
315
311
                self.data.global_options.add(short)
316
312
 
317
313
    def aliases(self):
318
 
        for alias, expansion in config.GlobalConfig().get_aliases().items():
 
314
        for alias, expansion in config.GlobalConfig().get_aliases().iteritems():
319
315
            for token in cmdline.split(expansion):
320
316
                if not token.startswith("-"):
321
317
                    self.user_aliases.setdefault(token, set()).add(alias)
332
328
        plugin_name = cmd.plugin_name()
333
329
        if plugin_name is not None:
334
330
            if (self.selected_plugins is not None and
335
 
                    plugin not in self.selected_plugins):
 
331
                plugin not in self.selected_plugins):
336
332
                return None
337
333
            plugin_data = self.data.plugins.get(plugin_name)
338
334
            if plugin_data is None:
347
343
        # ones while maintaining the actual command name unchanged.
348
344
        cmd_data.aliases.extend(cmd.aliases)
349
345
        cmd_data.aliases.extend(sorted([useralias
350
 
                                        for cmdalias in cmd_data.aliases
351
 
                                        if cmdalias in self.user_aliases
352
 
                                        for useralias in self.user_aliases[cmdalias]
353
 
                                        if useralias not in cmd_data.aliases]))
 
346
            for cmdalias in cmd_data.aliases
 
347
            if cmdalias in self.user_aliases
 
348
            for useralias in self.user_aliases[cmdalias]
 
349
            if useralias not in cmd_data.aliases]))
354
350
 
355
351
        opts = cmd.options()
356
 
        for optname, opt in sorted(opts.items()):
 
352
        for optname, opt in sorted(opts.iteritems()):
357
353
            cmd_data.options.extend(self.option(opt))
358
354
 
359
355
        if 'help' == name or 'help' in cmd.aliases:
360
356
            cmd_data.fixed_words = ('($cmds %s)' %
361
 
                                    " ".join(sorted(help_topics.topic_registry.keys())))
 
357
                " ".join(sorted(help_topics.topic_registry.keys())))
362
358
 
363
359
        return cmd_data
364
360
 
365
361
    def option(self, opt):
366
362
        optswitches = {}
367
 
        parser = option.get_optparser([opt])
 
363
        parser = option.get_optparser({opt.name: opt})
368
364
        parser = self.wrap_parser(optswitches, parser)
369
365
        optswitches.clear()
370
366
        opt.add_option(parser, opt.short_name())
374
370
            if enum_data:
375
371
                try:
376
372
                    enum_data.registry_keys = opt.registry.keys()
377
 
                except ImportError as e:
 
373
                except ImportError, e:
378
374
                    enum_data.error_messages.append(
379
375
                        "ERROR getting registry keys for '--%s': %s"
380
376
                        % (opt.name, str(e).split('\n')[0]))
389
385
 
390
386
    def wrap_parser(self, optswitches, parser):
391
387
        orig_add_option_group = parser.add_option_group
392
 
 
393
388
        def tweaked_add_option_group(*opts, **attrs):
394
389
            return self.wrap_container(optswitches,
395
 
                                       orig_add_option_group(*opts, **attrs))
 
390
                orig_add_option_group(*opts, **attrs))
396
391
        parser.add_option_group = tweaked_add_option_group
397
392
        return self.wrap_container(optswitches, parser)
398
393
 
399
394
 
400
 
def bash_completion_function(out, function_name="_brz", function_only=False,
 
395
def bash_completion_function(out, function_name="_bzr", function_only=False,
401
396
                             debug=False,
402
397
                             no_plugins=False, selected_plugins=None):
403
 
    dc = DataCollector(no_plugins=no_plugins,
404
 
                       selected_plugins=selected_plugins)
 
398
    dc = DataCollector(no_plugins=no_plugins, selected_plugins=selected_plugins)
405
399
    data = dc.collect()
406
400
    cg = BashCodeGen(data, function_name=function_name, debug=debug)
407
401
    if function_only:
417
411
    This command generates a shell function which can be used by bash to
418
412
    automatically complete the currently typed command when the user presses
419
413
    the completion key (usually tab).
420
 
 
 
414
    
421
415
    Commonly used like this:
422
 
        eval "`brz bash-completion`"
 
416
        eval "`bzr bash-completion`"
423
417
    """
424
418
 
425
419
    takes_options = [
426
420
        option.Option("function-name", short_name="f", type=str, argname="name",
427
 
                      help="Name of the generated function (default: _brz)"),
 
421
               help="Name of the generated function (default: _bzr)"),
428
422
        option.Option("function-only", short_name="o", type=None,
429
 
                      help="Generate only the shell function, don't enable it"),
 
423
               help="Generate only the shell function, don't enable it"),
430
424
        option.Option("debug", type=None, hidden=True,
431
 
                      help="Enable shell code useful for debugging"),
 
425
               help="Enable shell code useful for debugging"),
432
426
        option.ListOption("plugin", type=str, argname="name",
433
 
                          # param_name="selected_plugins", # doesn't work, bug #387117
434
 
                          help="Enable completions for the selected plugin"
435
 
                          + " (default: all plugins)"),
 
427
                # param_name="selected_plugins", # doesn't work, bug #387117
 
428
                help="Enable completions for the selected plugin"
 
429
                + " (default: all plugins)"),
436
430
        ]
437
431
 
438
432
    def run(self, **kwargs):
 
433
        import sys
 
434
        from bashcomp import bash_completion_function
439
435
        if 'plugin' in kwargs:
440
436
            # work around bug #387117 which prevents us from using param_name
441
437
            if len(kwargs['plugin']) > 0:
446
442
 
447
443
if __name__ == '__main__':
448
444
 
 
445
    import sys
449
446
    import locale
450
447
    import optparse
451
448
 
458
455
 
459
456
    parser = optparse.OptionParser(usage="%prog [-f NAME] [-o]")
460
457
    parser.add_option("--function-name", "-f", metavar="NAME",
461
 
                      help="Name of the generated function (default: _brz)")
 
458
                      help="Name of the generated function (default: _bzr)")
462
459
    parser.add_option("--function-only", "-o", action="store_true",
463
460
                      help="Generate only the shell function, don't enable it")
464
461
    parser.add_option("--debug", action="store_true",
465
462
                      help=optparse.SUPPRESS_HELP)
466
463
    parser.add_option("--no-plugins", action="store_true",
467
 
                      help="Don't load any brz plugins")
 
464
                      help="Don't load any bzr plugins")
468
465
    parser.add_option("--plugin", metavar="NAME", type="string",
469
466
                      dest="selected_plugins", default=[],
470
467
                      action="callback", callback=plugin_callback,
474
471
    if args:
475
472
        parser.error("script does not take positional arguments")
476
473
    kwargs = dict()
477
 
    for name, value in opts.__dict__.items():
 
474
    for name, value in opts.__dict__.iteritems():
478
475
        if value is not None:
479
476
            kwargs[name] = value
480
477