diff --git a/README.md b/README.md index 0610277..5170aec 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,8 @@ Vimspector requires: * Vim version 8.1 with at least patch 1264, or Neovim 0.4.3 * One of the following operating systems: * Linux - * macOS Mojave or pater + * macOS Mojave or later + * Windows (experimental) Why such a new vim ? Well 2 reasons: @@ -161,8 +162,9 @@ Why such a new vim ? Well 2 reasons: 2. Because there are Vim bugs that vimspector triggers that will frustrate you if you hit them. -Why no Windows support? Because it's effort and it's not a priority for the -author. PRs are welcome. +Why Windows support experimental? Because it's effort and it's not a priority +for the author. PRs are welcome to fix bugs. Windows will not be regularly +tested. Which Linux versions? I only test on Ubuntu 18.04 and later and RHEL 7. @@ -186,6 +188,12 @@ Workarounds are in place as follows: There is no workaroud for the lack of balloons; you'll just have to use `:VimspectorEval` or `:VimspectorWatch`, or switch to Vim. +## Windows differences + +The following features are not implemented for Windows: + +* Tailing the vimspector log in the Output Window. + ## Language dependencies The debug adapters themselves have certain runtime dependencies. They are diff --git a/autoload/vimspector/internal/job.vim b/autoload/vimspector/internal/job.vim index 4ed9ea8..18c5b08 100644 --- a/autoload/vimspector/internal/job.vim +++ b/autoload/vimspector/internal/job.vim @@ -30,7 +30,9 @@ endfunction function! s:_OnExit( channel, status ) abort echom 'Channel exit with status ' . a:status redraw - unlet s:job + if exists( 's:job' ) + unlet s:job + endif py3 _vimspector_session.OnServerExit( vim.eval( 'a:status' ) ) endfunction @@ -61,12 +63,17 @@ function! vimspector#internal#job#StartDebugSession( config ) abort \ } \ ) - echom 'Started job, status is: ' . job_status( s:job ) + if !exists( 's:job' ) + " The job died immediately after starting and we cleaned up + return v:false + endif + + let status = job_status( s:job ) + + echom 'Started job, status is: ' . status redraw - if job_status( s:job ) !=# 'run' - echom 'Unable to start job, status is: ' . job_status( s:job ) - redraw + if status !=# 'run' return v:false endif @@ -140,7 +147,7 @@ function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort \ } ) ) if job_status( s:commands[ a:category ][ index ] ) !=# 'run' - echom 'Unable to start job for ' . a:cmd + echom 'Unable to start job for ' . string( a:cmd ) redraw return v:none endif diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 2a87c4c..4c7abbb 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -30,7 +30,9 @@ function! s:_OnEvent( chan_id, data, event ) abort elseif a:event ==# 'exit' echom 'Channel exit with status ' . a:data redraw - unlet s:job + if exists( 's:job' ) + unlet s:job + endif " This causes terminal spam in neovim due to " https://github.com/neovim/neovim/issues/11725 py3 _vimspector_session.OnServerExit( vim.eval( 'a:data' ) ) diff --git a/autoload/vimspector/internal/neoterm.vim b/autoload/vimspector/internal/neoterm.vim index 627f570..f36c0db 100644 --- a/autoload/vimspector/internal/neoterm.vim +++ b/autoload/vimspector/internal/neoterm.vim @@ -28,10 +28,9 @@ let s:buffer_to_id = {} function! vimspector#internal#neoterm#PrepareEnvironment( env ) abort let old_env = {} - let new_env = copy( environ() ) for key in keys( a:env ) - if has_key( new_env, key ) - let old_env[ key ] = new_env[ key ] + if exists( '$' . key ) + let old_env[ key ] = getenv( key ) endif call setenv( key, a:env[ key ] ) endfor diff --git a/install_gadget.py b/install_gadget.py index 561af21..e7a5e7f 100755 --- a/install_gadget.py +++ b/install_gadget.py @@ -113,7 +113,7 @@ GADGETS = { 'adapters': { 'debugpy': { "command": [ - "python3", + sys.executable, "${gadgetDir}/debugpy/build/lib/debugpy/adapter" ], "name": "debugpy", diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 83c64f7..2f26e4f 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -879,7 +879,11 @@ class DebugSession( object ): status ) self.Clear() - self._connection.Reset() + if self._connection is not None: + # Can be None if the server dies _before_ StartDebugSession vim function + # returns + self._connection.Reset() + self._stackTraceView.ConnectionClosed() self._variablesView.ConnectionClosed() self._outputView.ConnectionClosed() diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index 53a0150..95ab19f 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -201,9 +201,24 @@ def MakeSymlink( in_folder, link, pointing_to ): RemoveIfExists( os.path.join( in_folder, link ) ) in_folder = os.path.abspath( in_folder ) - pointing_to = os.path.relpath( os.path.abspath( pointing_to ), - in_folder ) - os.symlink( pointing_to, os.path.join( in_folder, link ) ) + pointing_to_relative = os.path.relpath( os.path.abspath( pointing_to ), + in_folder ) + link_path = os.path.join( in_folder, link ) + + if install.GetOS() == 'windows': + # While symlinks do exist on Windows, they require elevated privileges, so + # let's use a directory junction which is all we need. + link_path = os.path.abspath( link_path ) + if os.path.isdir( link_path ): + os.rmdir( link_path ) + subprocess.check_call( [ 'cmd.exe', + '/c', + 'mklink', + '/J', + link_path, + pointing_to ] ) + else: + os.symlink( pointing_to_relative, link_path ) def CloneRepoTo( url, ref, destination ): diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index 43b1cc3..c02e84a 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from vimspector import utils +from vimspector import utils, install import vim import json @@ -49,10 +49,7 @@ class OutputView( object ): for b in set( BUFFER_MAP.values() ): self._CreateBuffer( b ) - self._CreateBuffer( - 'Vimspector', - file_name = vim.eval( 'expand( "~/.vimspector.log" )' ) ) - + self._CreateBuffer( 'Vimspector', file_name = utils.LOG_FILE ) self._ShowOutput( 'Console' ) def Print( self, categroy, text ): @@ -161,6 +158,10 @@ class OutputView( object ): if file_name is not None: assert cmd is None + if install.GetOS() == "windows": + # FIXME: Can't display fiels in windows (yet?) + return + cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ] if cmd is not None: diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 3ac41bf..3e58330 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -23,8 +23,10 @@ import string import functools -_log_handler = logging.FileHandler( os.path.expanduser( '~/.vimspector.log' ), - mode = 'w' ) +LOG_FILE = os.path.expanduser( os.path.join( '~', '.vimspector.log' ) ) + +_log_handler = logging.FileHandler( LOG_FILE, mode = 'w' ) + _log_handler.setFormatter( logging.Formatter( '%(asctime)s - %(levelname)s - %(message)s' ) ) @@ -40,7 +42,7 @@ SetUpLogging( _logger ) def BufferNumberForFile( file_name ): - return int( vim.eval( 'bufnr( "{0}", 1 )'.format( file_name ) ) ) + return int( vim.eval( "bufnr( '{0}', 1 )".format( Escape( file_name ) ) ) ) def BufferForFile( file_name ): @@ -50,7 +52,7 @@ def BufferForFile( file_name ): def OpenFileInCurrentWindow( file_name ): buffer_number = BufferNumberForFile( file_name ) try: - vim.command( 'bu {0}'.format( buffer_number ) ) + vim.current.buffer = vim.buffers[ buffer_number ] except vim.error as e: if 'E325' not in str( e ): raise