summaryrefslogtreecommitdiffstats
path: root/lldb/utils/vim-lldb/python-vim-lldb/vim_panes.py
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/utils/vim-lldb/python-vim-lldb/vim_panes.py')
-rw-r--r--lldb/utils/vim-lldb/python-vim-lldb/vim_panes.py669
1 files changed, 0 insertions, 669 deletions
diff --git a/lldb/utils/vim-lldb/python-vim-lldb/vim_panes.py b/lldb/utils/vim-lldb/python-vim-lldb/vim_panes.py
deleted file mode 100644
index b0c804d1962..00000000000
--- a/lldb/utils/vim-lldb/python-vim-lldb/vim_panes.py
+++ /dev/null
@@ -1,669 +0,0 @@
-#
-# This file contains implementations of the LLDB display panes in VIM
-#
-# The most generic way to define a new window is to inherit from VimPane
-# and to implement:
-# - get_content() - returns a string with the pane contents
-#
-# Optionally, to highlight text, implement:
-# - get_highlights() - returns a map
-#
-# And call:
-# - define_highlight(unique_name, colour)
-# at some point in the constructor.
-#
-#
-# If the pane shows some key-value data that is in the context of a
-# single frame, inherit from FrameKeyValuePane and implement:
-# - get_frame_content(self, SBFrame frame)
-#
-#
-# If the pane presents some information that can be retrieved with
-# a simple LLDB command while the subprocess is stopped, inherit
-# from StoppedCommandPane and call:
-# - self.setCommand(command, command_args)
-# at some point in the constructor.
-#
-# Optionally, you can implement:
-# - get_selected_line()
-# to highlight a selected line and place the cursor there.
-#
-#
-# FIXME: implement WatchlistPane to displayed watched expressions
-# FIXME: define interface for interactive panes, like catching enter
-# presses to change selected frame/thread...
-#
-
-import lldb
-import vim
-
-import sys
-
-# ==============================================================
-# Get the description of an lldb object or None if not available
-# ==============================================================
-
-# Shamelessly copy/pasted from lldbutil.py in the test suite
-
-
-def get_description(obj, option=None):
- """Calls lldb_obj.GetDescription() and returns a string, or None.
-
- For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
- option can be passed in to describe the detailed level of description
- desired:
- o lldb.eDescriptionLevelBrief
- o lldb.eDescriptionLevelFull
- o lldb.eDescriptionLevelVerbose
- """
- method = getattr(obj, 'GetDescription')
- if not method:
- return None
- tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
- if isinstance(obj, tuple):
- if option is None:
- option = lldb.eDescriptionLevelBrief
-
- stream = lldb.SBStream()
- if option is None:
- success = method(stream)
- else:
- success = method(stream, option)
- if not success:
- return None
- return stream.GetData()
-
-
-def get_selected_thread(target):
- """ Returns a tuple with (thread, error) where thread == None if error occurs """
- process = target.GetProcess()
- if process is None or not process.IsValid():
- return (None, VimPane.MSG_NO_PROCESS)
-
- thread = process.GetSelectedThread()
- if thread is None or not thread.IsValid():
- return (None, VimPane.MSG_NO_THREADS)
- return (thread, "")
-
-
-def get_selected_frame(target):
- """ Returns a tuple with (frame, error) where frame == None if error occurs """
- (thread, error) = get_selected_thread(target)
- if thread is None:
- return (None, error)
-
- frame = thread.GetSelectedFrame()
- if frame is None or not frame.IsValid():
- return (None, VimPane.MSG_NO_FRAME)
- return (frame, "")
-
-
-def _cmd(cmd):
- vim.command("call confirm('%s')" % cmd)
- vim.command(cmd)
-
-
-def move_cursor(line, col=0):
- """ moves cursor to specified line and col """
- cw = vim.current.window
- if cw.cursor[0] != line:
- vim.command("execute \"normal %dgg\"" % line)
-
-
-def winnr():
- """ Returns currently selected window number """
- return int(vim.eval("winnr()"))
-
-
-def bufwinnr(name):
- """ Returns window number corresponding with buffer name """
- return int(vim.eval("bufwinnr('%s')" % name))
-
-
-def goto_window(nr):
- """ go to window number nr"""
- if nr != winnr():
- vim.command(str(nr) + ' wincmd w')
-
-
-def goto_next_window():
- """ go to next window. """
- vim.command('wincmd w')
- return (winnr(), vim.current.buffer.name)
-
-
-def goto_previous_window():
- """ go to previously selected window """
- vim.command("execute \"normal \\<c-w>p\"")
-
-
-def have_gui():
- """ Returns True if vim is in a gui (Gvim/MacVim), False otherwise. """
- return int(vim.eval("has('gui_running')")) == 1
-
-
-class PaneLayout(object):
- """ A container for a (vertical) group layout of VimPanes """
-
- def __init__(self):
- self.panes = {}
-
- def havePane(self, name):
- """ Returns true if name is a registered pane, False otherwise """
- return name in self.panes
-
- def prepare(self, panes=[]):
- """ Draw panes on screen. If empty list is provided, show all. """
-
- # If we can't select a window contained in the layout, we are doing a
- # first draw
- first_draw = not self.selectWindow(True)
- did_first_draw = False
-
- # Prepare each registered pane
- for name in self.panes:
- if name in panes or len(panes) == 0:
- if first_draw:
- # First window in layout will be created with :vsp, and
- # closed later
- vim.command(":vsp")
- first_draw = False
- did_first_draw = True
- self.panes[name].prepare()
-
- if did_first_draw:
- # Close the split window
- vim.command(":q")
-
- self.selectWindow(False)
-
- def contains(self, bufferName=None):
- """ Returns True if window with name bufferName is contained in the layout, False otherwise.
- If bufferName is None, the currently selected window is checked.
- """
- if not bufferName:
- bufferName = vim.current.buffer.name
-
- for p in self.panes:
- if bufferName is not None and bufferName.endswith(p):
- return True
- return False
-
- def selectWindow(self, select_contained=True):
- """ Selects a window contained in the layout (if select_contained = True) and returns True.
- If select_contained = False, a window that is not contained is selected. Returns False
- if no group windows can be selected.
- """
- if select_contained == self.contains():
- # Simple case: we are already selected
- return True
-
- # Otherwise, switch to next window until we find a contained window, or
- # reach the first window again.
- first = winnr()
- (curnum, curname) = goto_next_window()
-
- while not select_contained == self.contains(
- curname) and curnum != first:
- (curnum, curname) = goto_next_window()
-
- return self.contains(curname) == select_contained
-
- def hide(self, panes=[]):
- """ Hide panes specified. If empty list provided, hide all. """
- for name in self.panes:
- if name in panes or len(panes) == 0:
- self.panes[name].destroy()
-
- def registerForUpdates(self, p):
- self.panes[p.name] = p
-
- def update(self, target, controller):
- for name in self.panes:
- self.panes[name].update(target, controller)
-
-
-class VimPane(object):
- """ A generic base class for a pane that displays stuff """
- CHANGED_VALUE_HIGHLIGHT_NAME_GUI = 'ColorColumn'
- CHANGED_VALUE_HIGHLIGHT_NAME_TERM = 'lldb_changed'
- CHANGED_VALUE_HIGHLIGHT_COLOUR_TERM = 'darkred'
-
- SELECTED_HIGHLIGHT_NAME_GUI = 'Cursor'
- SELECTED_HIGHLIGHT_NAME_TERM = 'lldb_selected'
- SELECTED_HIGHLIGHT_COLOUR_TERM = 'darkblue'
-
- MSG_NO_TARGET = "Target does not exist."
- MSG_NO_PROCESS = "Process does not exist."
- MSG_NO_THREADS = "No valid threads."
- MSG_NO_FRAME = "No valid frame."
-
- # list of defined highlights, so we avoid re-defining them
- highlightTypes = []
-
- def __init__(self, owner, name, open_below=False, height=3):
- self.owner = owner
- self.name = name
- self.buffer = None
- self.maxHeight = 20
- self.openBelow = open_below
- self.height = height
- self.owner.registerForUpdates(self)
-
- def isPrepared(self):
- """ check window is OK """
- if self.buffer is None or len(
- dir(self.buffer)) == 0 or bufwinnr(self.name) == -1:
- return False
- return True
-
- def prepare(self, method='new'):
- """ check window is OK, if not then create """
- if not self.isPrepared():
- self.create(method)
-
- def on_create(self):
- pass
-
- def destroy(self):
- """ destroy window """
- if self.buffer is None or len(dir(self.buffer)) == 0:
- return
- vim.command('bdelete ' + self.name)
-
- def create(self, method):
- """ create window """
-
- if method != 'edit':
- belowcmd = "below" if self.openBelow else ""
- vim.command('silent %s %s %s' % (belowcmd, method, self.name))
- else:
- vim.command('silent %s %s' % (method, self.name))
-
- self.window = vim.current.window
-
- # Set LLDB pane options
- vim.command("setlocal buftype=nofile") # Don't try to open a file
- vim.command("setlocal noswapfile") # Don't use a swap file
- vim.command("set nonumber") # Don't display line numbers
- # vim.command("set nowrap") # Don't wrap text
-
- # Save some parameters and reference to buffer
- self.buffer = vim.current.buffer
- self.width = int(vim.eval("winwidth(0)"))
- self.height = int(vim.eval("winheight(0)"))
-
- self.on_create()
- goto_previous_window()
-
- def update(self, target, controller):
- """ updates buffer contents """
- self.target = target
- if not self.isPrepared():
- # Window is hidden, or otherwise not ready for an update
- return
-
- original_cursor = self.window.cursor
-
- # Select pane
- goto_window(bufwinnr(self.name))
-
- # Clean and update content, and apply any highlights.
- self.clean()
-
- if self.write(self.get_content(target, controller)):
- self.apply_highlights()
-
- cursor = self.get_selected_line()
- if cursor is None:
- # Place the cursor at its original position in the window
- cursor_line = min(original_cursor[0], len(self.buffer))
- cursor_col = min(
- original_cursor[1], len(
- self.buffer[
- cursor_line - 1]))
- else:
- # Place the cursor at the location requested by a VimPane
- # implementation
- cursor_line = min(cursor, len(self.buffer))
- cursor_col = self.window.cursor[1]
-
- self.window.cursor = (cursor_line, cursor_col)
-
- goto_previous_window()
-
- def get_selected_line(self):
- """ Returns the line number to move the cursor to, or None to leave
- it where the user last left it.
- Subclasses implement this to define custom behaviour.
- """
- return None
-
- def apply_highlights(self):
- """ Highlights each set of lines in each highlight group """
- highlights = self.get_highlights()
- for highlightType in highlights:
- lines = highlights[highlightType]
- if len(lines) == 0:
- continue
-
- cmd = 'match %s /' % highlightType
- lines = ['\%' + '%d' % line + 'l' for line in lines]
- cmd += '\\|'.join(lines)
- cmd += '/'
- vim.command(cmd)
-
- def define_highlight(self, name, colour):
- """ Defines highlihght """
- if name in VimPane.highlightTypes:
- # highlight already defined
- return
-
- vim.command(
- "highlight %s ctermbg=%s guibg=%s" %
- (name, colour, colour))
- VimPane.highlightTypes.append(name)
-
- def write(self, msg):
- """ replace buffer with msg"""
- self.prepare()
-
- msg = str(msg.encode("utf-8", "replace")).split('\n')
- try:
- self.buffer.append(msg)
- vim.command("execute \"normal ggdd\"")
- except vim.error:
- # cannot update window; happens when vim is exiting.
- return False
-
- move_cursor(1, 0)
- return True
-
- def clean(self):
- """ clean all datas in buffer """
- self.prepare()
- vim.command(':%d')
- #self.buffer[:] = None
-
- def get_content(self, target, controller):
- """ subclasses implement this to provide pane content """
- assert(0 and "pane subclass must implement this")
- pass
-
- def get_highlights(self):
- """ Subclasses implement this to provide pane highlights.
- This function is expected to return a map of:
- { highlight_name ==> [line_number, ...], ... }
- """
- return {}
-
-
-class FrameKeyValuePane(VimPane):
-
- def __init__(self, owner, name, open_below):
- """ Initialize parent, define member variables, choose which highlight
- to use based on whether or not we have a gui (MacVim/Gvim).
- """
-
- VimPane.__init__(self, owner, name, open_below)
-
- # Map-of-maps key/value history { frame --> { variable_name,
- # variable_value } }
- self.frameValues = {}
-
- if have_gui():
- self.changedHighlight = VimPane.CHANGED_VALUE_HIGHLIGHT_NAME_GUI
- else:
- self.changedHighlight = VimPane.CHANGED_VALUE_HIGHLIGHT_NAME_TERM
- self.define_highlight(VimPane.CHANGED_VALUE_HIGHLIGHT_NAME_TERM,
- VimPane.CHANGED_VALUE_HIGHLIGHT_COLOUR_TERM)
-
- def format_pair(self, key, value, changed=False):
- """ Formats a key/value pair. Appends a '*' if changed == True """
- marker = '*' if changed else ' '
- return "%s %s = %s\n" % (marker, key, value)
-
- def get_content(self, target, controller):
- """ Get content for a frame-aware pane. Also builds the list of lines that
- need highlighting (i.e. changed values.)
- """
- if target is None or not target.IsValid():
- return VimPane.MSG_NO_TARGET
-
- self.changedLines = []
-
- (frame, err) = get_selected_frame(target)
- if frame is None:
- return err
-
- output = get_description(frame)
- lineNum = 1
-
- # Retrieve the last values displayed for this frame
- frameId = get_description(frame.GetBlock())
- if frameId in self.frameValues:
- frameOldValues = self.frameValues[frameId]
- else:
- frameOldValues = {}
-
- # Read the frame variables
- vals = self.get_frame_content(frame)
- for (key, value) in vals:
- lineNum += 1
- if len(frameOldValues) == 0 or (
- key in frameOldValues and frameOldValues[key] == value):
- output += self.format_pair(key, value)
- else:
- output += self.format_pair(key, value, True)
- self.changedLines.append(lineNum)
-
- # Save values as oldValues
- newValues = {}
- for (key, value) in vals:
- newValues[key] = value
- self.frameValues[frameId] = newValues
-
- return output
-
- def get_highlights(self):
- ret = {}
- ret[self.changedHighlight] = self.changedLines
- return ret
-
-
-class LocalsPane(FrameKeyValuePane):
- """ Pane that displays local variables """
-
- def __init__(self, owner, name='locals'):
- FrameKeyValuePane.__init__(self, owner, name, open_below=True)
-
- # FIXME: allow users to customize display of args/locals/statics/scope
- self.arguments = True
- self.show_locals = True
- self.show_statics = True
- self.show_in_scope_only = True
-
- def format_variable(self, var):
- """ Returns a Tuple of strings "(Type) Name", "Value" for SBValue var """
- val = var.GetValue()
- if val is None:
- # If the value is too big, SBValue.GetValue() returns None; replace
- # with ...
- val = "..."
-
- return ("(%s) %s" % (var.GetTypeName(), var.GetName()), "%s" % val)
-
- def get_frame_content(self, frame):
- """ Returns list of key-value pairs of local variables in frame """
- vals = frame.GetVariables(self.arguments,
- self.show_locals,
- self.show_statics,
- self.show_in_scope_only)
- return [self.format_variable(x) for x in vals]
-
-
-class RegistersPane(FrameKeyValuePane):
- """ Pane that displays the contents of registers """
-
- def __init__(self, owner, name='registers'):
- FrameKeyValuePane.__init__(self, owner, name, open_below=True)
-
- def format_register(self, reg):
- """ Returns a tuple of strings ("name", "value") for SBRegister reg. """
- name = reg.GetName()
- val = reg.GetValue()
- if val is None:
- val = "..."
- return (name, val.strip())
-
- def get_frame_content(self, frame):
- """ Returns a list of key-value pairs ("name", "value") of registers in frame """
-
- result = []
- for register_sets in frame.GetRegisters():
- # hack the register group name into the list of registers...
- result.append((" = = %s =" % register_sets.GetName(), ""))
-
- for reg in register_sets:
- result.append(self.format_register(reg))
- return result
-
-
-class CommandPane(VimPane):
- """ Pane that displays the output of an LLDB command """
-
- def __init__(self, owner, name, open_below, process_required=True):
- VimPane.__init__(self, owner, name, open_below)
- self.process_required = process_required
-
- def setCommand(self, command, args=""):
- self.command = command
- self.args = args
-
- def get_content(self, target, controller):
- output = ""
- if not target:
- output = VimPane.MSG_NO_TARGET
- elif self.process_required and not target.GetProcess():
- output = VimPane.MSG_NO_PROCESS
- else:
- (success, output) = controller.getCommandOutput(
- self.command, self.args)
- return output
-
-
-class StoppedCommandPane(CommandPane):
- """ Pane that displays the output of an LLDB command when the process is
- stopped; otherwise displays process status. This class also implements
- highlighting for a single line (to show a single-line selected entity.)
- """
-
- def __init__(self, owner, name, open_below):
- """ Initialize parent and define highlight to use for selected line. """
- CommandPane.__init__(self, owner, name, open_below)
- if have_gui():
- self.selectedHighlight = VimPane.SELECTED_HIGHLIGHT_NAME_GUI
- else:
- self.selectedHighlight = VimPane.SELECTED_HIGHLIGHT_NAME_TERM
- self.define_highlight(VimPane.SELECTED_HIGHLIGHT_NAME_TERM,
- VimPane.SELECTED_HIGHLIGHT_COLOUR_TERM)
-
- def get_content(self, target, controller):
- """ Returns the output of a command that relies on the process being stopped.
- If the process is not in 'stopped' state, the process status is returned.
- """
- output = ""
- if not target or not target.IsValid():
- output = VimPane.MSG_NO_TARGET
- elif not target.GetProcess() or not target.GetProcess().IsValid():
- output = VimPane.MSG_NO_PROCESS
- elif target.GetProcess().GetState() == lldb.eStateStopped:
- (success, output) = controller.getCommandOutput(
- self.command, self.args)
- else:
- (success, output) = controller.getCommandOutput("process", "status")
- return output
-
- def get_highlights(self):
- """ Highlight the line under the cursor. Users moving the cursor has
- no effect on the selected line.
- """
- ret = {}
- line = self.get_selected_line()
- if line is not None:
- ret[self.selectedHighlight] = [line]
- return ret
- return ret
-
- def get_selected_line(self):
- """ Subclasses implement this to control where the cursor (and selected highlight)
- is placed.
- """
- return None
-
-
-class DisassemblyPane(CommandPane):
- """ Pane that displays disassembly around PC """
-
- def __init__(self, owner, name='disassembly'):
- CommandPane.__init__(self, owner, name, open_below=True)
-
- # FIXME: let users customize the number of instructions to disassemble
- self.setCommand("disassemble", "-c %d -p" % self.maxHeight)
-
-
-class ThreadPane(StoppedCommandPane):
- """ Pane that displays threads list """
-
- def __init__(self, owner, name='threads'):
- StoppedCommandPane.__init__(self, owner, name, open_below=False)
- self.setCommand("thread", "list")
-
-# FIXME: the function below assumes threads are listed in sequential order,
-# which turns out to not be the case. Highlighting of selected thread
-# will be disabled until this can be fixed. LLDB prints a '*' anyways
-# beside the selected thread, so this is not too big of a problem.
-# def get_selected_line(self):
-# """ Place the cursor on the line with the selected entity.
-# Subclasses should override this to customize selection.
-# Formula: selected_line = selected_thread_id + 1
-# """
-# (thread, err) = get_selected_thread(self.target)
-# if thread is None:
-# return None
-# else:
-# return thread.GetIndexID() + 1
-
-
-class BacktracePane(StoppedCommandPane):
- """ Pane that displays backtrace """
-
- def __init__(self, owner, name='backtrace'):
- StoppedCommandPane.__init__(self, owner, name, open_below=False)
- self.setCommand("bt", "")
-
- def get_selected_line(self):
- """ Returns the line number in the buffer with the selected frame.
- Formula: selected_line = selected_frame_id + 2
- FIXME: the above formula hack does not work when the function return
- value is printed in the bt window; the wrong line is highlighted.
- """
-
- (frame, err) = get_selected_frame(self.target)
- if frame is None:
- return None
- else:
- return frame.GetFrameID() + 2
-
-
-class BreakpointsPane(CommandPane):
-
- def __init__(self, owner, name='breakpoints'):
- super(
- BreakpointsPane,
- self).__init__(
- owner,
- name,
- open_below=False,
- process_required=False)
- self.setCommand("breakpoint", "list")
OpenPOWER on IntegriCloud