File: subcmd.py

package info (click to toggle)
pydb 1.26-2
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 2,512 kB
  • ctags: 1,061
  • sloc: python: 4,200; perl: 2,479; lisp: 866; sh: 780; makefile: 633; ansic: 16
file content (177 lines) | stat: -rw-r--r-- 6,369 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
"""Handles gdb-like subcommand processing."""
__revision="$Id: subcmd.py,v 1.9 2007/02/04 13:00:12 rockyb Exp $"
# -*- coding: utf-8 -*-
#   Copyright (C) 2006, 2007 Rocky Bernstein
#
#    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.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
#    02110-1301 USA.

class Subcmd:
    """Gdb-like subcommand handling """
    def __init__(self, name, doc):
        self.name    = name
        self.doc     = doc
        self.subcmds = {}
        self.cmdlist = []

    def lookup(self, subcmd_prefix):
        """Find subcmd in self.subcmds"""
        for subcmd_name in self.subcmds.keys():
            if subcmd_name.startswith(subcmd_prefix) \
               and len(subcmd_prefix) >= self.subcmds[subcmd_name]['min']:
                return self.subcmds[subcmd_name]
        return None

    def _subcmd_helper(self, subcmd_name, obj, label=False, strip=False):
        """Show help for a single subcommand"""
        if label:
            obj.msg_nocr("%s %s --" % (self.name, subcmd_name))

        entry = self.lookup(subcmd_name)
        if entry:
            d = entry['doc']
            if strip:
                # Limit the help message to one line (delimited by '\n')
                if '\n' in d:
                    d = d[:d.find('\n')]
                # If the last character is a period, remove it.
                if d[-1] == '.': d = d[:d.find('.')]
            obj.msg(d)
            return
        obj.undefined_cmd("help", subcmd_name)

    def add(self, subcmd_name, subcmd_cb, min_len=0, in_list=True):
        """Add subcmd to the available subcommands for this object.
        It will have the supplied docstring, and subcmd_cb will be called
        when we want to run the command. min_len is the minimum length
        allowed to abbreviate the command. in_list indicates with the
        show command will be run when giving a list of all sub commands
        of this object. Some commands have long output like "show commands"
        so we might not want to show that.
        """
        self.subcmds[subcmd_name] = {
            "callback": subcmd_cb,
            "name"    : subcmd_name,
            "doc"     : subcmd_cb.__doc__,
            "in_list" : in_list,
            "min"     : min_len}

        # We keep a list of subcommands to assist command completion
        self.cmdlist.append(subcmd_name)

    def do(self, obj, subcmd_name, arg):
        """Run subcmd_name with args using obj for the environent"""
        entry=self.lookup(subcmd_name)
        if entry:
            entry['callback'](arg)
        else:
            obj.undefined_cmd(self.name, subcmd_name)

    # Note: format of help is compatible with ddd.
    def help(self, obj, *args):
        """help for subcommands."""

        subcmd_prefix = args[0]
        if not subcmd_prefix or len(subcmd_prefix) == 0:
            obj.msg(self.doc)
            obj.msg("""
List of %s subcommands:
""" % (self.name))
            for subcmd_name in self.list():
                self._subcmd_helper(subcmd_name, obj, True, True)
            return

        entry = self.lookup(subcmd_prefix)
        if entry:
            self._subcmd_helper(entry['name'], obj)
        else:
            obj.errmsg("Unknown 'help %s' subcommand %s"
                       % (self.name, subcmd_prefix))

    def list(self):
        l = self.subcmds.keys()
        l.sort()
        return l


# When invoked as main program, invoke the debugger on a script
if __name__ == '__main__':

    class FakeGdb:
        "A Mock Gdb class"
        def msg_nocr(self, msg): print msg,
        def msg(self, msg): print msg
        def errmsg(self, msg): print msg

        def info_args(self, arg):
            "Print the arguments of the current function."
            print "a=1, b=2"
        def info_break(self, arg):
            "Without argument, list info about all breakpoints"
            print "no breakpoints"
        def set_args(self, arg):
            """Set argument list to give program being debugged when it is started"""
            print "Not done yet"
        def set_basename(self, arg):
            "Set short filenames (the basename) in debug output"
            print "basename changed to %s" % arg

        def show_args(self, arg):
            """Show argument list to give debugged program on start"""
            print "Argument list to give program is ''"
        def show_basename(self, arg):
            "Show if we are to show short of long filenames"
            print "basename is off."
        def show_cmdtrace(self, arg):
            "Show if we are to show debugger commands"
            print "cmdtraces is on."


    gdb = FakeGdb()
    infocmd = Subcmd('info',
"""Generic command for showing things about the program being debugged. """)

    infocmd.add('args', gdb.info_args)
    infocmd.add('break', gdb.info_break)
    showcmd = Subcmd('show',
    """Generic command for showing things about the debugger.""")
    showcmd.add('args', gdb.show_args)
    showcmd.add('basename', gdb.show_basename,)
    showcmd.add('cmdtrace', gdb.show_cmdtrace)

    showcmd.help(gdb, '')
    print "-" * 20
    showcmd.help(gdb, "args")
    print "-" * 20
    showcmd.do(gdb, "args", "")
    print "-" * 20
    infocmd.help(gdb, '')
    print "-" * 20
    infocmd.help(gdb, 'basename')
    setcmd = Subcmd('set',
    """This command modifies parts of the debugger environment.
You can see these environment settings with the 'show' command.""")

    setcmd.add('args', gdb.set_args)
    setcmd.add('basename', gdb.set_basename)
    print "-" * 20
    setcmd.help(gdb, '')
    print "-" * 20
    setcmd.help(gdb, 'basename')
    print "-" * 20
    setcmd.do(gdb, 'basename', 'off')

    print showcmd.list()