From b6a9cba52ebe718de00df1c935367e3c8d8bf113 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 29 May 2018 00:39:37 +0100 Subject: [PATCH] Support the bash debugger This required working around some sort of bug where the server returns an invalid content length. Either that or we are somehow processing the same message twice with additional escaping? It's really strange. --- .vimspector.json | 25 ++++++++++++++++++ README.md | 8 +++--- python3/vimspector/code.py | 14 +++++----- .../vimspector/debug_adapter_connection.py | 20 ++++++++++---- python3/vimspector/debug_session.py | 26 +++++++++++-------- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/.vimspector.json b/.vimspector.json index 06dfdc5..a2fb97a 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -21,6 +21,13 @@ "node", "/Users/ben/.vscode/extensions/ms-python.python-2018.4.0/out/client/debugger/Main.js" ] + }, + "bashdb": { + "name": "bashdb", + "command": [ + "node", + "/Users/ben/.vscode/extensions/rogalmic.bash-debug-0.2.0/out/bashDebug.js" + ] } }, "configurations": { @@ -72,6 +79,24 @@ "program": "/Users/ben/.vim/bundle/vimspector/support/test/cpp/simple_c_program/test", "MIMode": "lldb" } + }, + "bashdb": { + "adapter": "bashdb", + "configuration": { + "type": "bashdb", + "request": "launch", + "name": "Bash-Debug (simplest configuration)", + "program": "/Users/ben/.vim/bundle/YouCompleteMe/install.sh", + "args": [], + "cwd": "/Users/ben/.vim/bundle/YouCompleteMe", + "pathBash": "bash", + "pathBashdb": "bashdb", + "pathCat": "cat", + "pathMkfifo": "mkfifo", + "pathPkill": "pkill", + "showDebugOutput": true, + "trace": true + } } } } diff --git a/README.md b/README.md index c63d877..0b7784c 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ breakpoint. * Expand result with ``. * Delete with ``. -## Stack Trraces +## Stack Traces * In the threads window, use `` to expand/collapse. * Use `` on a stack frame to jump to it. @@ -241,12 +241,12 @@ Known not to work: Currently on the author's environment which is macOS. -The plugin _might_ work on other unix-like environments but it hasn't been -tested. It will almost cerainly not work on Windows. +The plugin _might_ work on other UNIX-like environments but it hasn't been +tested. It will almost certainly not work on Windows. Requires: -- Vim 8.1 compiled with python 3 support +- Vim 8.1 compiled with python 3 support. # FAQ diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 058e986..2329c20 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -57,20 +57,21 @@ class CodeView( object ): self._signs[ 'vimspectorPC' ] = None if not frame or not frame[ 'source' ]: - return + return False vim.current.window = self._window - buffer_number = vim.eval( 'bufnr( "{0}", 1 )'.format( - frame[ 'source' ][ 'path' ] ) ) + buffer_number = int( vim.eval( 'bufnr( "{0}", 1 )'.format( + frame[ 'source' ][ 'path' ] ) ) ) try: vim.command( 'bu {0}'.format( buffer_number ) ) + self._window.cursor = ( frame[ 'line' ], frame[ 'column' ] ) except vim.error as e: if 'E325' not in str( e ): - raise - - self._window.cursor = ( frame[ 'line' ], frame[ 'column' ] ) + self._logger.exception( + 'Unexpected error from vim: {0}'.format( str( e ) ) ) + return False self._signs[ 'vimspectorPC' ] = self._next_sign_id self._next_sign_id += 1 @@ -80,6 +81,7 @@ class CodeView( object ): frame[ 'line' ], frame[ 'source' ][ 'path' ] ) ) + return True def Clear( self ): if self._signs[ 'vimspectorPC' ]: diff --git a/python3/vimspector/debug_adapter_connection.py b/python3/vimspector/debug_adapter_connection.py index 6b83ca4..c4a137d 100644 --- a/python3/vimspector/debug_adapter_connection.py +++ b/python3/vimspector/debug_adapter_connection.py @@ -80,24 +80,34 @@ class DebugAdapterConnection( object ): self._Write( data ) def _ReadHeaders( self ): - headers = self._buffer.split( bytes( '\r\n\r\n', 'utf-8' ), 1 ) + parts = self._buffer.split( bytes( '\r\n\r\n', 'utf-8' ), 1 ) - if len( headers ) > 1: - for header_line in headers[ 0 ].split( bytes( '\r\n', 'utf-8' ) ): + if len( parts ) > 1: + headers = parts[ 0 ] + for header_line in headers.split( bytes( '\r\n', 'utf-8' ) ): if header_line.strip(): key, value = str( header_line, 'utf-8' ).split( ':', 1 ) self._headers[ key ] = value # Chomp (+4 for the 2 newlines which were the separator) # self._buffer = self._buffer[ len( headers[ 0 ] ) + 4 : ] - self._buffer = headers[ 1 ] + self._buffer = parts[ 1 ] self._SetState( 'READ_BODY' ) return # otherwise waiting for more data def _ReadBody( self ): - content_length = int( self._headers[ 'Content-Length' ] ) + try: + content_length = int( self._headers[ 'Content-Length' ] ) + except KeyError: + # Ug oh. We seem to have all the headers, but no Content-Length + # Skip to reading headers. Because, what else can we do. + self._logger.error( 'Missing Content-Length header in: {0}'.format( + json.dumps( self._headers ) ) ) + self._buffer = bytes( '', 'utf-8' ) + self._SetState( 'READ_HEADER' ) + return if len( self._buffer ) < content_length: # Need more data diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index cf6b5ae..747db92 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -293,7 +293,7 @@ class DebugSession( object ): self.SetCurrentFrame( None ) def SetCurrentFrame( self, frame ): - self._codeView.SetCurrentFrame( frame ) + ret = self._codeView.SetCurrentFrame( frame ) if frame: self._variablesView.LoadScopes( frame ) @@ -302,6 +302,8 @@ class DebugSession( object ): self._stackTraceView.Clear() self._variablesView.Clear() + return ret + def _StartDebugAdapter( self ): self._logger.info( 'Starting debug adapter with: {0}'.format( json.dumps( self._adapter ) ) ) @@ -383,9 +385,15 @@ class DebugSession( object ): 'command': 'initialize', 'arguments': { 'adapterID': adapter_config.get( 'name', 'adapter' ), + 'clientID': 'vimspector', + 'clientName': 'vimspector', 'linesStartAt1': True, 'columnsStartAt1': True, + 'locale': 'en_GB', 'pathFormat': 'path', + 'supportsVariableType': True, + 'supportsVariablePaging': False, + 'supportsRunInTerminalRequest': True }, } ) @@ -407,18 +415,14 @@ class DebugSession( object ): def OnEvent_initialized( self, message ): self._SendBreakpoints() - self._connection.DoRequest( None, { - 'command': 'configurationDone', - } ) - - self._stackTraceView.LoadThreads( True ) + self._connection.DoRequest( + lambda msg: self._stackTraceView.LoadThreads( True ), + { + 'command': 'configurationDone', + } + ) def OnEvent_thread( self, message ): - if message[ 'body' ][ 'reason' ] == 'started': - pass - elif message[ 'body' ][ 'reason' ] == 'exited': - pass - self._stackTraceView.OnThreadEvent( message[ 'body' ] ) def OnEvent_breakpoint( self, message ):